diff --git a/.gitignore b/.gitignore index d39a0a4a07f33856d938f8873ce7daafa0d520c1..49bdcfc69b005b866af44e5e53d03204a0286dbb 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ /com.oracle.truffle.r.native/builtinlibs/lib/* /com.oracle.truffle.r.native/library/*/lib/* /com.oracle.truffle.r.native/library/stats/src/fft.c +/com.oracle.truffle.r.native/library/tools/src/gramRd.c /com.oracle.truffle.r.native/platform.mk /com.oracle.truffle.r.native/gnur/Makeconf.done /com.oracle.truffle.r.native/gnur/platform.mk.temp* @@ -23,9 +24,16 @@ /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.test.native/packages/copy_recommended +/com.oracle.truffle.r.test.native/packages/recommended /com.oracle.truffle.r.test.native/packages/*/lib/* -/com.oracle.truffle.r.test/rpackages/testrlibs_user /com.oracle.truffle.r.test.native/urand/lib/liburand.so +/tmptest/ +/com.oracle.truffle.r.release/lib/ +/com.oracle.truffle.r.release/library/ +/com.oracle.truffle.r.release/LICENSE +/com.oracle.truffle.r.release/COPYRIGHT +/com.oracle.truffle.r.release/README.md /DEPARSE_ERROR /Rpkgsource/* /install.cran.logs/ diff --git a/LICENSE.md b/LICENSE similarity index 100% rename from LICENSE.md rename to LICENSE diff --git a/ci.hocon b/ci.hocon index 8060d69d637e98a826a688dd697e37d944610c3d..d96fd01f504f0bc43ac62d7bcb1748c314e8cb9a 100644 --- a/ci.hocon +++ b/ci.hocon @@ -1,20 +1,23 @@ +# This is part of the framework used by FastR for continuous integration testing. +# It is not intended that this "code" is directly usable by third-party developers +# but it provide details on the commands that are used and these should be +# executable in isolation; see further comments below. + +# java 7 is needed by Truffle (for now) java7 : {name : oraclejdk, version : "7", platformspecific: true} -#java8 : {name : oraclejdk, version : "8u66", platformspecific: true} -java8 : {name : labsjdk, version : "8u92-jvmci-0.17", platformspecific: true} +# java 8 must be a jvmci enabled variant +java8 : {name : labsjdk, version : "8u92-jvmci-0.21", platformspecific: true} -common : { - packages : { - git : ">=1.8.3" - mercurial : ">=2.2" - "pip:astroid" : "==1.1.0" - "pip:pylint" : "==1.1.0" - make : ">=3.83" - gcc-build-essentials : ">=4.9.1" # GCC 4.9.0 fails on cluster - readline : "==6.3" - } - environment : { +java8Downloads : { + downloads : { + EXTRA_JAVA_HOMES : { pathlist :[ + ${java7} + ]} + JAVA_HOME : ${java8} } - logs : [ +} + +logfiles : [ "fastr_errors.log" "com.oracle.truffle.r.native/gnur/R-*/gnur_configure.log" "com.oracle.truffle.r.native/gnur/R-*/gnur_make.log" @@ -22,26 +25,81 @@ common : { "com.oracle.truffle.r.native/gnur/libiconv-*/iconv_configure.log" "com.oracle.truffle.r.native/gnur/libiconv-*/iconv_make.log" ] - timelimit : "1:00:00" -} -gateCmd : ["mx", "--strict-compliance", "originalgate", "--strict-mode", "-t"] +# This is needed by all (Linux) builds but is specific to the module system employed +# on the CI cluster. Not all of the modules are needed by FastR but all are needed by the +# embedded GNU R that is built within FastR. -java8Downloads : { - downloads : { - EXTRA_JAVA_HOMES : { pathlist :[ - ${java7} - ]} - JAVA_HOME : ${java8} +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"""" } } -gateTest : ${common} ${java8Downloads} { +packagesLinux : ${pkgEnvironment} { + packages : { + git : ">=1.8.3" + mercurial : ">=2.2" + "pip:astroid" : "==1.1.0" + "pip:pylint" : "==1.1.0" + make : ">=3.83" + gcc-build-essentials : "==4.9.1" # GCC 4.9.0 fails on cluster + readline : "==6.3" + pcre : ">=8.38" + z : ">=1.2.8" + } +} + +packagesDarwin : { + "pip:astroid" : "==1.1.0" + "pip:pylint" : "==1.1.0" + "xz" : "" + # assume pcre/z system installed +} + +# Common settings for all builds but note that it uses the Linux package settings, +# so these must be overridden in any darwin builds + +common : ${java8Downloads} ${packagesLinux} { + logs: ${logfiles} + timelimit : "1:00:00" +} + +# Every "pull request" (PR) is subject to a series of "gate" commands that must pass +# for the PR to be accepted into the master branch. The gate commands are run under +# the "mx" tool. This defines a common prefix for all gate commands. The "-t" +# arg indicates the exact set of gate "tasks" that will be run. + +gateCmd : ["mx", "--strict-compliance", "rgate", "--strict-mode", "-t"] + +# currently disabled gate commands: FindBugs,Checkheaders,Distribution Overlap Check,BuildJavaWithEcj + +# The standard set of gate tasks: the actual executable tests are in the "UnitTests" task. + +gateTestCommon : ${common} { run : [ - ${gateCmd} ["Versions,JDKReleaseInfo,Pylint,Canonicalization Check,BuildJavaWithJavac,UnitTests: ExpectedTestOutput file check,UnitTests"] + ${gateCmd} ["Versions,JDKReleaseInfo,BuildJavaWithJavac,UnitTests: ExpectedTestOutput file check,UnitTests"] ] } +gateTestLinux : ${gateTestCommon} { +} + +darwinEnvironment : { + environment : { + PATH : "/usr/local/bin:$JAVA_HOME/bin:$PATH" + F77: "/usr/local/bin/gfortran-4.9" + } +} + +gateTestDarwin : ${gateTestCommon} ${darwinEnvironment} { + packages : ${packagesDarwin} { + } +} + +# This performs a number of "style" checks on the code to ensure it confirms to the project standards. + gateStyle : ${common} { # need pyhocon fix downloads : { @@ -50,7 +108,7 @@ gateStyle : ${common} { JDT : {name: ecj, version: "4.5.1", platformspecific: false} ECLIPSE : {name: eclipse, version: "4.5.2", platformspecific: true} } - environment : ${common.environment} { + environment : { ECLIPSE_EXE : "$ECLIPSE/eclipse" } run : [ @@ -58,19 +116,21 @@ gateStyle : ${common} { ] } -rbcheck : ${common} ${java8Downloads} { +# This check runs diagnostics on the implementation of the R "builtins" in FastR, e.g., that the argument processing is sound. + +rbcheck : ${common} { run : [ ${gateCmd} ["Versions,JDKReleaseInfo,BuildJavaWithJavac"] ["mx", "rbcheck"] ["mx", "rbdiag", "-n", "-m"] - ] + ] } -# currently disabled gate commands: FindBugs,Checkheaders,Distribution Overlap Check,BuildJavaWithEcj +# The standard set of gate builds. N.B. the style/builtin checks are only run on Linux as they are not OS-dependent. builds = [ - ${gateTest} {capabilities : [linux, amd64], targets : [gate, post-merge], name: "gate-test-linux-amd64"} + ${gateTestLinux} {capabilities : [linux, amd64], targets : [gate, post-merge], name: "gate-test-linux-amd64"} + ${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"} -# ${gateTest} {capabilities : [linux, sparcv9], targets : [gate, post-merge], name: "gate-test-linux-sparcv9"} ] diff --git a/com.oracle.truffle.r.agents/src/com/oracle/truffle/r/agents/objsize/ObjSizeAgent.java b/com.oracle.truffle.r.agents/src/com/oracle/truffle/r/agents/objsize/ObjSizeAgent.java new file mode 100644 index 0000000000000000000000000000000000000000..073d6bf9a9587b005d09f1d185aa4ff9f4cb4c65 --- /dev/null +++ b/com.oracle.truffle.r.agents/src/com/oracle/truffle/r/agents/objsize/ObjSizeAgent.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, 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.agents.objsize; + +import java.lang.instrument.Instrumentation; + +public class ObjSizeAgent { + private static Instrumentation instrumentation; + + public static void agentmain(@SuppressWarnings("unused") String agentArgs, Instrumentation inst) { + instrumentation = inst; + } + + public static long objectSize(Object obj) { + return instrumentation.getObjectSize(obj); + } +} 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 479dbaca13b04118744e13dd78c39f673ca27dad..9fbc99886e15a80afb408dab067cabdf1ea63e59 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 @@ -29,6 +29,7 @@ import java.util.Map; import java.util.stream.Collectors; import com.oracle.truffle.api.CallTarget; +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; @@ -39,8 +40,8 @@ import com.oracle.truffle.api.frame.Frame; 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.impl.FindContextNode; import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; @@ -50,17 +51,21 @@ import com.oracle.truffle.r.library.graphics.RGraphics; import com.oracle.truffle.r.nodes.RASTBuilder; 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.RBuiltinPackages; import com.oracle.truffle.r.nodes.builtin.base.printer.ValuePrinterNode; import com.oracle.truffle.r.nodes.control.BreakException; import com.oracle.truffle.r.nodes.control.NextException; -import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.nodes.function.CallMatcherNode.CallMatcherGenericNode; +import com.oracle.truffle.r.nodes.function.PromiseHelperNode; +import com.oracle.truffle.r.nodes.function.call.CallRFunctionNode; +import com.oracle.truffle.r.nodes.function.visibility.GetVisibilityNode; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.nodes.instrumentation.RInstrumentation; import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.ExitException; import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.JumpToTopLevelException; -import com.oracle.truffle.r.runtime.ExitException; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RError; @@ -89,6 +94,7 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPromise; 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.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; @@ -279,8 +285,8 @@ final class REngine implements Engine, Engine.Timings { @Override public RExpression parse(Map<String, Object> constants, Source source) throws ParseException { List<RSyntaxNode> list = parseImpl(constants, source); - Object[] data = list.stream().map(node -> RASTUtils.createLanguageElement(node.asRNode())).toArray(); - return RDataFactory.createExpression(RDataFactory.createList(data)); + Object[] data = list.stream().map(node -> RASTUtils.createLanguageElement(node)).toArray(); + return RDataFactory.createExpression(data); } @Override @@ -288,23 +294,38 @@ final class REngine implements Engine, Engine.Timings { RParserFactory.Parser<RSyntaxNode> parser = RParserFactory.getParser(); RootCallTarget callTarget = parser.rootFunction(source, name, new RASTBuilder(constants)); FrameSlotChangeMonitor.initializeEnclosingFrame(callTarget.getRootNode().getFrameDescriptor(), enclosingFrame); - return RDataFactory.createFunction(name, callTarget, null, enclosingFrame); + RFunction func = RDataFactory.createFunction(name, callTarget, null, enclosingFrame); + RInstrumentation.checkDebugRequested(func); + return func; } @Override public CallTarget parseToCallTarget(Source source) throws ParseException { List<RSyntaxNode> statements = parseImpl(null, source); - return Truffle.getRuntime().createCallTarget(new PolyglotEngineRootNode(statements)); + return Truffle.getRuntime().createCallTarget(new PolyglotEngineRootNode(statements, createSourceSection(statements))); + } + + private static SourceSection createSourceSection(List<RSyntaxNode> statements) { + // All statements come from the same "Source" + if (statements.size() == 1) { + return statements.get(0).getSourceSection(); + } else { + Source source = statements.get(0).getSourceSection().getSource(); + return source.createSection(0, statements.get(statements.size() - 1).getSourceSection().getCharEndIndex()); + } } private final class PolyglotEngineRootNode extends RootNode { private final List<RSyntaxNode> statements; + private final boolean printResult; - @SuppressWarnings("unchecked") @Child private FindContextNode<RContext> findContext = (FindContextNode<RContext>) TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode(); + @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode(); - PolyglotEngineRootNode(List<RSyntaxNode> statements) { - super(TruffleRLanguage.class, SourceSection.createUnavailable("repl", RSource.Internal.REPL_WRAPPER.string), new FrameDescriptor()); + PolyglotEngineRootNode(List<RSyntaxNode> statements, SourceSection sourceSection) { + super(TruffleRLanguage.class, sourceSection, new FrameDescriptor()); + // can't print if initializing the system in embedded mode (no builtins yet) + this.printResult = !sourceSection.getSource().getName().equals(RSource.Internal.INIT_EMBEDDED.string); this.statements = statements; } @@ -315,13 +336,14 @@ final class REngine implements Engine, Engine.Timings { */ @Override public Object execute(VirtualFrame frame) { - RContext oldContext = RContext.threadLocalContext.get(); - RContext newContext = findContext.executeFindContext(); - RContext.threadLocalContext.set(newContext); + RContext oldContext = RContext.getThreadLocalInstance(); + RContext newContext = TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext); + RContext.setThreadLocalInstance(newContext); try { Object lastValue = RNull.instance; - for (RSyntaxNode node : statements) { - RootCallTarget callTarget = doMakeCallTarget(node.asRNode(), RSource.Internal.REPL_WRAPPER.string, true, true); + for (int i = 0; i < statements.size(); i++) { + RSyntaxNode node = statements.get(i); + RootCallTarget callTarget = doMakeCallTarget(node.asRNode(), RSource.Internal.REPL_WRAPPER.string, printResult, true); lastValue = callTarget.call(newContext.stateREnvironment.getGlobalFrame()); } return lastValue; @@ -335,17 +357,21 @@ final class REngine implements Engine, Engine.Timings { } catch (Throwable t) { throw t; } finally { - RContext.threadLocalContext.set(oldContext); + RContext.setThreadLocalInstance(oldContext); } } } @Override + @TruffleBoundary public Object eval(RExpression exprs, REnvironment envir, RCaller caller) { Object result = RNull.instance; for (int i = 0; i < exprs.getLength(); i++) { - Object obj = RASTUtils.checkForRSymbol(exprs.getDataAt(i)); - if (obj instanceof RLanguage) { + Object obj = exprs.getDataAt(i); + if (obj instanceof RSymbol) { + result = ReadVariableNode.lookupAny(((RSymbol) obj).getName(), envir.getFrame(), false); + caller.setVisibility(true); + } else if (obj instanceof RLanguage) { result = evalNode(((RLanguage) obj).getRep().asRSyntaxNode(), envir, caller); } else { result = obj; @@ -355,12 +381,14 @@ final class REngine implements Engine, Engine.Timings { } @Override + @TruffleBoundary public Object eval(RLanguage expr, REnvironment envir, RCaller caller) { return evalNode(expr.getRep().asRSyntaxNode(), envir, caller); } @Override public Object eval(RExpression expr, MaterializedFrame frame) { + CompilerAsserts.neverPartOfCompilation(); Object result = null; for (int i = 0; i < expr.getLength(); i++) { result = expr.getDataAt(i); @@ -374,6 +402,7 @@ final class REngine implements Engine, Engine.Timings { @Override public Object eval(RLanguage expr, MaterializedFrame frame) { + CompilerAsserts.neverPartOfCompilation(); RNode n = (RNode) expr.getRep(); // TODO perhaps this ought to be being checked earlier if (n instanceof ConstantNode) { @@ -390,7 +419,7 @@ final class REngine implements Engine, Engine.Timings { MaterializedFrame actualFrame = frame; if (actualFrame == null) { Frame current = Utils.getActualCurrentFrame(); - if (current == null) { + if (current == null || !RArguments.isRFrame(current)) { // special case, e.g. in parser and an error is thrown actualFrame = REnvironment.globalEnv().getFrame(); } else { @@ -407,8 +436,7 @@ final class REngine implements Engine, Engine.Timings { newArgs[i] = PromiseHelperNode.evaluateSlowPath(null, (RPromise) arg); } } - Object[] rArgs = RArguments.create(func, caller == null ? RArguments.getCall(actualFrame) : caller, actualFrame, newArgs, null); - return func.getTarget().call(rArgs); + return CallRFunctionNode.executeSlowpath(func, caller == null ? RArguments.getCall(actualFrame) : caller, actualFrame, newArgs, null); } private Object evalNode(RSyntaxElement exprRep, REnvironment envir, RCaller caller) { @@ -469,6 +497,8 @@ final class REngine implements Engine, Engine.Timings { private final boolean topLevel; @Child private RNode body; + @Child private GetVisibilityNode visibility = GetVisibilityNode.create(); + @Child private SetVisibilityNode setVisibility = SetVisibilityNode.create(); protected AnonymousRootNode(RNode body, String description, boolean printResult, boolean topLevel) { super(TruffleRLanguage.class, null, new FrameDescriptor()); @@ -499,13 +529,14 @@ final class REngine implements Engine, Engine.Timings { assert checkResult(result); if (printResult && result != null) { assert topLevel; - if (context.isVisible()) { + if (visibility.execute(vf)) { printResult(result); } } if (topLevel) { RErrorHandling.printWarnings(suppressWarnings); } + setVisibility.executeEndOfFunction(vf); } catch (RError e) { CompilerDirectives.transferToInterpreter(); throw e; @@ -561,7 +592,7 @@ final class REngine implements Engine, Engine.Timings { public void printResult(Object originalResult) { Object result = evaluatePromise(originalResult); result = RRuntime.asAbstractVector(result); - if (result instanceof RTypedValue) { + if (result instanceof RTypedValue || result instanceof TruffleObject) { Object resultValue = evaluatePromise(result); Object printMethod = REnvironment.globalEnv().findFunction("print"); RFunction function = (RFunction) evaluatePromise(printMethod); @@ -569,7 +600,7 @@ final class REngine implements Engine, Engine.Timings { ((RShareable) resultValue).incRefCount(); } MaterializedFrame callingFrame = REnvironment.globalEnv().getFrame(); - function.getTarget().call(RArguments.create(function, RCaller.createInvalid(callingFrame), callingFrame, new Object[]{resultValue, RMissing.instance}, null)); + CallRFunctionNode.executeSlowpath(function, RCaller.createInvalid(callingFrame), callingFrame, new Object[]{resultValue, RMissing.instance}, null); if (resultValue instanceof RShareable && !((RShareable) resultValue).isSharedPermanent()) { ((RShareable) resultValue).decRefCount(); } @@ -583,13 +614,10 @@ final class REngine implements Engine, Engine.Timings { Object result = evaluatePromise(originalResult); result = RRuntime.asAbstractVector(result); // this supports printing of non-R values (via toString for now) - if (result instanceof RTypedValue) { + if (result instanceof RTypedValue || result instanceof TruffleObject) { return ValuePrinterNode.prettyPrint(result); } else if (result == null) { return "[external object (null)]"; - } else if (result instanceof TruffleObject) { - assert !(result instanceof RTypedValue); - return "[external object]"; } else if (result instanceof CharSequence) { return "[1] \"" + String.valueOf(result) + "\""; } else { 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 9744d89ebda248d647be26c292d7a621fa0cf48e..5267b65c3b23ac7727aa16c60915587ba23389b8 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 @@ -22,6 +22,12 @@ */ package com.oracle.truffle.r.engine; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -31,6 +37,8 @@ import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.r.engine.shell.RCommand; +import com.oracle.truffle.r.engine.shell.RscriptCommand; import com.oracle.truffle.r.nodes.RASTBuilder; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.RRootNode; @@ -39,6 +47,8 @@ import com.oracle.truffle.r.nodes.access.WriteVariableNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinRootNode; +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.helpers.DebugHandling; import com.oracle.truffle.r.nodes.builtin.helpers.TraceHandling; import com.oracle.truffle.r.nodes.control.AbstractLoopNode; @@ -47,7 +57,6 @@ import com.oracle.truffle.r.nodes.control.IfNode; import com.oracle.truffle.r.nodes.control.ReplacementNode; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; import com.oracle.truffle.r.nodes.function.FunctionExpressionNode; -import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.runtime.Arguments; import com.oracle.truffle.r.runtime.ArgumentsSignature; @@ -57,7 +66,6 @@ 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.RRuntimeASTAccess; -import com.oracle.truffle.r.runtime.RSerialize; import com.oracle.truffle.r.runtime.ReturnException; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.context.Engine; @@ -65,6 +73,7 @@ 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.RAttributes; +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.RLanguage; @@ -73,10 +82,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.RUnboundValue; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; -import com.oracle.truffle.r.runtime.env.REnvironment; -import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; @@ -386,54 +392,6 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { } } - @Override - public Object serialize(RSerialize.State state, Object obj) { - if (obj instanceof RFunction) { - RFunction f = (RFunction) obj; - FunctionDefinitionNode fdn = (FunctionDefinitionNode) f.getRootNode(); - REnvironment env = REnvironment.frameToEnvironment(f.getEnclosingFrame()); - state.openPairList().setTag(env); - fdn.serializeImpl(state); - return state.closePairList(); - } else if (obj instanceof RLanguage) { - RLanguage lang = (RLanguage) obj; - RSyntaxNode node = lang.getRep().asRSyntaxNode(); - state.openPairList(SEXPTYPE.LANGSXP); - node.serializeImpl(state); - return state.closePairList(); - } else if (obj instanceof RPromise) { - RPromise promise = (RPromise) obj; - RSyntaxNode node = (RSyntaxNode) RASTUtils.unwrap(promise.getRep()); - /* - * If the promise is evaluated, we store the value (in car) and the tag is set to RNull, - * else we record the environment in the tag and store RUnboundValue. In either case we - * record the expression. - */ - Object value; - Object tag; - if (promise.isEvaluated()) { - value = promise.getValue(); - tag = RNull.instance; - } else { - value = RUnboundValue.instance; - tag = promise.getFrame() == null ? REnvironment.globalEnv() : REnvironment.frameToEnvironment(promise.getFrame()); - } - state.openPairList().setTag(tag); - state.setCar(value); - state.openPairList(); - node.serializeImpl(state); - state.setCdr(state.closePairList()); - return state.closePairList(); - } else { - throw RInternalError.unimplemented("serialize"); - } - } - - @Override - public void serializeNode(RSerialize.State state, Object node) { - ((RBaseNode) node).serialize(state); - } - @Override public ArgumentsSignature getArgumentsSignature(RFunction f) { return ((RRootNode) f.getRootNode()).getSignature(); @@ -634,16 +592,6 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { return false; } - @Override - public RBaseNode createReadVariableNode(String name) { - return RASTUtils.createReadVariableNode(name); - } - - @Override - public RBaseNode createConstantNode(Object o) { - return ConstantNode.create(o); - } - @Override public boolean enableDebug(RFunction func, boolean once) { return DebugHandling.enableDebug(func, "", RNull.instance, once, false); @@ -659,4 +607,133 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { return DebugHandling.undebug(func); } + @Override + public Object rcommandMain(String[] args, String[] env, boolean intern) { + IORedirect redirect = handleIORedirect(args, intern); + Object result = RCommand.doMain(redirect.args, env, false, redirect.in, redirect.out); + return redirect.getInternResult(result); + } + + @Override + public Object rscriptMain(String[] args, String[] env, boolean intern) { + IORedirect redirect = handleIORedirect(args, intern); + // TODO argument parsing can fail with ExitException, which needs to be handled correctly in + // nested context + Object result = RscriptCommand.doMain(redirect.args, env, false, redirect.in, redirect.out); + return redirect.getInternResult(result); + } + + private static final class IORedirect { + private final InputStream in; + private final OutputStream out; + private final String[] args; + private final boolean intern; + + private IORedirect(InputStream in, OutputStream out, String[] args, boolean intern) { + this.in = in; + this.out = out; + this.args = args; + this.intern = intern; + } + + private Object getInternResult(Object result) { + if (intern) { + int status = (int) result; + ByteArrayOutputStream bos = (ByteArrayOutputStream) out; + String s = new String(bos.toByteArray()); + RStringVector sresult; + if (s.length() == 0) { + sresult = RDataFactory.createEmptyStringVector(); + } else { + String[] lines = s.split("\n"); + sresult = RDataFactory.createStringVector(lines, RDataFactory.COMPLETE_VECTOR); + } + if (status != 0) { + sresult.setAttr("status", RDataFactory.createIntVectorFromScalar(status)); + } + return sresult; + } else { + return result; + } + + } + } + + private static IORedirect handleIORedirect(String[] args, boolean intern) { + /* + * This code is primarily intended to handle the "system" .Internal so the possible I/O + * redirects are taken from the system/system2 R code. N.B. stdout redirection is never set + * if "intern == true. Both input and output can be redirected to /dev/null. + */ + InputStream in = System.in; + OutputStream out = System.out; + ArrayList<String> newArgsList = new ArrayList<>(); + int i = 0; + while (i < args.length) { + String arg = args[i]; + if (arg.equals("<")) { + String file; + if (i < args.length - 1) { + file = Utils.tildeExpand(Utils.unShQuote(args[i + 1])); + } else { + throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "redirect missing"); + } + try { + in = new FileInputStream(file); + } catch (IOException ex) { + throw RError.error(RError.NO_CALLER, RError.Message.NO_SUCH_FILE, file); + } + arg = null; + i++; + } else if (arg.startsWith("2>")) { + if (arg.equals("2>&1")) { + // happens anyway + } else { + assert !intern; + throw RError.nyi(RError.NO_CALLER, "stderr redirect"); + } + arg = null; + } else if (arg.startsWith(">")) { + assert !intern; + arg = null; + throw RError.nyi(RError.NO_CALLER, "stdout redirect"); + } + if (arg != null) { + newArgsList.add(arg); + } + i++; + } + String[] newArgs; + if (newArgsList.size() == args.length) { + newArgs = args; + } else { + newArgs = new String[newArgsList.size()]; + newArgsList.toArray(newArgs); + } + // to implement intern, we create a ByteArryOutputStream to capture the output + if (intern) { + out = new ByteArrayOutputStream(); + } + return new IORedirect(in, out, newArgs, intern); + } + + @Override + public String encodeDouble(double x) { + return DoubleVectorPrinter.encodeReal(x); + } + + @Override + public String encodeDouble(double x, int digits) { + return DoubleVectorPrinter.encodeReal(x, digits); + } + + @Override + public String encodeComplex(RComplex x) { + return ComplexVectorPrinter.encodeComplex(x); + } + + @Override + public String encodeComplex(RComplex x, int digits) { + return ComplexVectorPrinter.encodeComplex(x, digits); + } } 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 dc9ba058337ef8f48d23465a6b0f6085c07ffc49..2c708749458aa496473e4daa4360cb53a350fc37 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 @@ -22,17 +22,20 @@ */ package com.oracle.truffle.r.engine; -import java.io.Closeable; -import java.io.IOException; import java.util.Locale; import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; +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.instrumentation.Instrumenter; import com.oracle.truffle.api.instrumentation.ProvidedTags; import com.oracle.truffle.api.instrumentation.StandardTags; import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.r.engine.interop.RForeignAccessFactoryImpl; import com.oracle.truffle.r.nodes.RASTBuilder; @@ -41,7 +44,6 @@ import com.oracle.truffle.r.nodes.instrumentation.RSyntaxTags; import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RAccuracyInfo; import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RPerfStats; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RVersionInfo; import com.oracle.truffle.r.runtime.TempPathName; @@ -49,6 +51,7 @@ import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.context.Engine.IncompleteSourceException; import com.oracle.truffle.r.runtime.context.Engine.ParseException; import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.context.RContext.RCloseable; import com.oracle.truffle.r.runtime.ffi.Load_RFFIFactory; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; import com.oracle.truffle.r.runtime.instrument.RPackageSource; @@ -69,19 +72,19 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> { private static void initialize() { try { Load_RFFIFactory.initialize(true); - RPerfStats.initialize(); Locale.setDefault(Locale.ROOT); RAccuracyInfo.initialize(); RVersionInfo.initialize(); TempPathName.initialize(); RPackageSource.initialize(); - RContext.initialize(new RASTBuilder(), new RRuntimeASTAccessImpl(), RBuiltinPackages.getInstance(), new RForeignAccessFactoryImpl()); + } catch (Throwable t) { + t.printStackTrace(); Utils.rSuicide("error during R language initialization"); } } - private static boolean initialized; + private static boolean systemInitialized; public static final TruffleRLanguage INSTANCE = new TruffleRLanguage(); @@ -96,12 +99,20 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> { } @Override - protected RContext createContext(Env env) { - boolean initialContext = !initialized; - if (!initialized) { + protected void initializeContext(RContext context) throws Exception { + if (!systemInitialized) { FastROptions.initialize(); initialize(); - initialized = true; + systemInitialized = true; + } + context.initializeContext(); + } + + @Override + protected RContext createContext(Env env) { + boolean initialContext = !systemInitialized; + if (initialContext) { + RContext.initializeGlobalState(new RASTBuilder(), new RRuntimeASTAccessImpl(), RBuiltinPackages.getInstance(), new RForeignAccessFactoryImpl()); } RContext result = RContext.create(env, env.lookup(Instrumenter.class), initialContext); return result; @@ -120,31 +131,32 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> { } @Override + @TruffleBoundary @SuppressWarnings("try") - protected CallTarget parse(Source source, Node context, String... argumentNames) throws IOException { - try (Closeable c = RContext.withinContext(findContext(createFindContextNode()))) { + protected CallTarget parse(Source source, Node context, String... argumentNames) throws com.oracle.truffle.api.vm.IncompleteSourceException { + try (RCloseable c = RContext.withinContext(findContext(createFindContextNode()))) { try { return RContext.getEngine().parseToCallTarget(source); } catch (IncompleteSourceException e) { throw new com.oracle.truffle.api.vm.IncompleteSourceException(e); } catch (ParseException e) { - return new CallTarget() { + return Truffle.getRuntime().createCallTarget(new RootNode(TruffleRLanguage.class, null, new FrameDescriptor()) { @Override - public Object call(Object... arguments) { + public Object execute(VirtualFrame frame) { try { throw e.throwAsRError(); } catch (RError e2) { return null; } } - }; + }); } catch (RError e) { - return new CallTarget() { + return Truffle.getRuntime().createCallTarget(new RootNode(TruffleRLanguage.class, null, new FrameDescriptor()) { @Override - public Object call(Object... arguments) { + public Object execute(VirtualFrame frame) { return null; } - }; + }); } } } @@ -170,7 +182,7 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> { } @Override - protected Object evalInContext(Source source, Node node, MaterializedFrame frame) throws IOException { + protected Object evalInContext(Source source, Node node, MaterializedFrame frame) { return RContext.getEngine().parseAndEval(source, frame, false); } } 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 1d56ee2a3edd84573e14c7a4d6aa018bd2aca12a..751f3de92a21b8538597d41e82489963b8644a92 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 @@ -28,20 +28,19 @@ 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.Factory10; +import com.oracle.truffle.api.interop.ForeignAccess.Factory18; import com.oracle.truffle.api.interop.Message; 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.builtin.base.InfixFunctions.AccessArraySubscriptBuiltin; import com.oracle.truffle.r.nodes.control.RLengthNode; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.data.RLogical; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -public final class RAbstractVectorAccessFactory implements Factory10 { +public final class RAbstractVectorAccessFactory implements Factory18 { static class VectorSizeNode extends RootNode { @@ -60,7 +59,6 @@ public final class RAbstractVectorAccessFactory implements Factory10 { abstract static class VectorReadNode extends RootNode { @CompilationFinal private boolean lengthAccess; - @Child private AccessArraySubscriptBuiltin builtin; @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); @Child private RLengthNode lengthNode = RLengthNode.create(); @@ -177,4 +175,9 @@ public final class RAbstractVectorAccessFactory implements Factory10 { public CallTarget accessNew(int argumentsLength) { return null; } + + @Override + public CallTarget accessKeys() { + return null; + } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..8f9ab7d176f7d28c7f146c6fee1a5ada9946749d --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2016, 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.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.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; + +@MessageResolution(receiverType = REnvironment.class, language = TruffleRLanguage.class) +public class REnvironmentMR { + + @Resolve(message = "IS_BOXED") + public abstract static class REnvironmentIsBoxedNode extends Node { + protected Object access(@SuppressWarnings("unused") REnvironment receiver) { + return false; + } + } + + @Resolve(message = "HAS_SIZE") + public abstract static class REnvironmentHasSizeNode extends Node { + protected Object access(@SuppressWarnings("unused") REnvironment receiver) { + return true; + } + } + + @Resolve(message = "IS_NULL") + public abstract static class REnvironmentIsNullNode extends Node { + protected Object access(@SuppressWarnings("unused") REnvironment receiver) { + return false; + } + } + + @Resolve(message = "READ") + public abstract static class REnvironmentReadNode 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, REnvironment receiver, String field) { + try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { + return extract.applyAccessField(frame, receiver, field); + } + } + } + + @Resolve(message = "WRITE") + public abstract static class REnvironmentWriteNode extends Node { + @Child private ReplaceVectorNode extract = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode(); + + @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 x = extract.apply(frame, receiver, new Object[]{field}, value); + return x; + } + } + } + + @CanResolve + public abstract static class REnvironmentCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof REnvironment; + } + } + +} 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 b37357ee1787014d2bcd870e24d5418273f932f5..03f73455c63146019f8c9bb5a4ffdfead920049b 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 @@ -36,6 +36,7 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RTruffleObject; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.env.REnvironment; public final class RForeignAccessFactoryImpl implements RForeignAccessFactory { @@ -82,6 +83,8 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory { 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)) { 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 eb7902f3aa4943a2f097733fddb00104afe7efe3..f74aee87f9c372fa61e130bb3f2f357440b30867 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 @@ -22,10 +22,6 @@ */ package com.oracle.truffle.r.engine.interop; -import java.io.Closeable; -import java.io.IOException; - -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameSlot; @@ -42,6 +38,7 @@ import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RArguments; 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; @@ -69,16 +66,13 @@ public class RFunctionMR { VirtualFrame dummyFrame = Truffle.getRuntime().createVirtualFrame(dummyFrameArgs, emptyFrameDescriptor); RArgsValuesAndNames actualArgs = new RArgsValuesAndNames(arguments, ArgumentsSignature.empty(arguments.length)); - try (Closeable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { + try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { try { dummyFrame.setObject(slot, actualArgs); return call.execute(dummyFrame, receiver); } finally { dummyFrame.setObject(slot, null); } - } catch (IOException e) { - CompilerDirectives.transferToInterpreter(); - throw new RuntimeException(e); } } } 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 66fe5c9da31282deabc8ac4cd4c35bc5cc626921..e1b29ff4d097c17b20b90f33cd768a97bfffcf2c 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 @@ -33,6 +33,9 @@ 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.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RList; @MessageResolution(receiverType = RList.class, language = TruffleRLanguage.class) @@ -62,34 +65,54 @@ public class RListMR { @Resolve(message = "READ") public abstract static class RListReadNode 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, RList receiver, String field) { - Object x = extract.applyAccessField(frame, receiver, field); - return x; + try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { + return extract.applyAccessField(frame, receiver, field); + } } } @Resolve(message = "WRITE") public abstract static class RListWriteNode extends Node { @Child private ReplaceVectorNode extract = 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) { - 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(); + 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; + } + } + } + + @Resolve(message = "KEYS") + public abstract static class RListKeysNode extends Node { + @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode(); + private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + + @SuppressWarnings("try") + protected Object access(RList receiver) { + try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { + return receiver.getNames(attrProfiles); } - 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/shell/EmbeddedConsoleHandler.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java index 0e5040ee582fd8423eda42aeb596e77094ab5c8d..c1f46024b85c0c6d56b9d85448b95cdbb95b5d57 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.engine.shell; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RInterfaceCallbacks; import com.oracle.truffle.r.runtime.RStartParams; import com.oracle.truffle.r.runtime.context.ConsoleHandler; @@ -51,6 +52,7 @@ public class EmbeddedConsoleHandler implements ConsoleHandler { this.startParams = startParams; } + @TruffleBoundary private REmbedRFFI getREmbedRFFI() { if (rEmbedRFFI == null) { rEmbedRFFI = RFFIFactory.getRFFI().getREmbedRFFI(); @@ -58,7 +60,7 @@ public class EmbeddedConsoleHandler implements ConsoleHandler { if (startParams.getNoReadline()) { delegate = new DefaultConsoleHandler(System.in, System.out); } else { - delegate = new JLineConsoleHandler(startParams); + delegate = new JLineConsoleHandler(startParams, System.in, System.out); } } } @@ -66,6 +68,7 @@ public class EmbeddedConsoleHandler implements ConsoleHandler { } @Override + @TruffleBoundary public void println(String s) { getREmbedRFFI(); if (delegate == null) { @@ -78,6 +81,7 @@ public class EmbeddedConsoleHandler implements ConsoleHandler { } @Override + @TruffleBoundary public void print(String s) { getREmbedRFFI(); if (delegate == null) { @@ -89,6 +93,7 @@ public class EmbeddedConsoleHandler implements ConsoleHandler { } @Override + @TruffleBoundary public void printErrorln(String s) { getREmbedRFFI(); if (delegate == null) { @@ -101,6 +106,7 @@ public class EmbeddedConsoleHandler implements ConsoleHandler { } @Override + @TruffleBoundary public void printError(String s) { getREmbedRFFI(); if (delegate == null) { @@ -112,6 +118,7 @@ public class EmbeddedConsoleHandler implements ConsoleHandler { } @Override + @TruffleBoundary public String readLine() { getREmbedRFFI(); if (delegate == null) { @@ -132,6 +139,7 @@ public class EmbeddedConsoleHandler implements ConsoleHandler { } @Override + @TruffleBoundary public void setPrompt(String prompt) { this.prompt = prompt; if (delegate != null) { 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 dc3db25f769838496fc5eb497fa461721ed4e104..b43a2c2e2911c12453ab5b330f91c635124c2b67 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 @@ -24,6 +24,8 @@ package com.oracle.truffle.r.engine.shell; import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.io.PrintWriter; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -42,9 +44,9 @@ class JLineConsoleHandler implements ConsoleHandler { private final boolean isInteractive; private final PrintWriter printWriter; - JLineConsoleHandler(RStartParams startParams) { + JLineConsoleHandler(RStartParams startParams, InputStream inStream, OutputStream outStream) { try { - console = new ConsoleReader(System.in, System.out); + console = new ConsoleReader(inStream, outStream); console.setHandleUserInterrupt(true); console.setExpandEvents(false); } catch (IOException 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 30a134642b932dbd8197084dfad5f5562ecdf335..fd95aaabe749d59b4aef809227a831c9db6fd6dd 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 @@ -29,6 +29,8 @@ import java.io.Console; import java.io.EOFException; import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.nio.file.Files; import java.util.List; @@ -66,14 +68,18 @@ public class RCommand { // CheckStyle: stop system..print check public static void main(String[] args) { - RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, false); - options.printHelpAndVersion(); - PolyglotEngine vm = createPolyglotEngineFromCommandLine(options, false); + doMain(args, null, true, System.in, System.out); // never returns - readEvalPrint(vm); throw RInternalError.shouldNotReachHere(); } + 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); + } + /** * The standard R script escapes spaces to "~+~" in "-e" and "-f" commands. */ @@ -81,7 +87,7 @@ public class RCommand { return input.replace("~+~", " "); } - static PolyglotEngine createPolyglotEngineFromCommandLine(RCmdOptions options, boolean embedded) { + static PolyglotEngine createPolyglotEngineFromCommandLine(RCmdOptions options, boolean embedded, boolean initial, InputStream inStream, OutputStream outStream, String[] env) { RStartParams rsp = new RStartParams(options, embedded); String fileArg = options.getString(FILE); @@ -120,13 +126,21 @@ public class RCommand { List<String> lines; String filePath; try { - File file = new File(fileArg); + /* + * If initial==false, ~ expansion will not have been done and the open will fail. + * It's harmless to always do it. + */ + File file = new File(Utils.tildeExpand(fileArg)); lines = Files.readAllLines(file.toPath()); filePath = file.getCanonicalPath(); } catch (IOException e) { - throw Utils.rSuicide("cannot open file '" + fileArg + "': " + e.getMessage()); + if (initial) { + throw Utils.rSuicide(String.format(RError.Message.NO_SUCH_FILE.message, fileArg)); + } else { + throw RError.error(RError.NO_CALLER, RError.Message.NO_SUCH_FILE, fileArg); + } } - consoleHandler = new StringConsoleHandler(lines, System.out, filePath); + consoleHandler = new StringConsoleHandler(lines, outStream, filePath); } else if (options.getStringList(EXPR) != null) { List<String> exprs = options.getStringList(EXPR); for (int i = 0; i < exprs.size(); i++) { @@ -137,7 +151,7 @@ public class RCommand { } // cf GNU R rsp.setInteractive(false); - consoleHandler = new StringConsoleHandler(exprs, System.out, RSource.Internal.EXPRESSION_INPUT.string); + consoleHandler = new StringConsoleHandler(exprs, outStream, RSource.Internal.EXPRESSION_INPUT.string); } else { /* * GnuR behavior differs from the manual entry for {@code interactive} in that {@code @@ -148,23 +162,28 @@ public class RCommand { * should be lazy, as these may not be necessary and can cause hangs if stdin has been * redirected. */ - Console sysConsole = System.console(); + Console sysConsole = System.console(); // TODO fix for context sessions boolean isInteractive = options.getBoolean(INTERACTIVE) || sysConsole != null; if (!isInteractive && rsp.getSaveAction() != SA_TYPE.SAVE && rsp.getSaveAction() != SA_TYPE.NOSAVE) { - throw Utils.rSuicide("you must specify '--save', '--no-save' or '--vanilla'"); + String msg = "you must specify '--save', '--no-save' or '--vanilla'"; + if (initial) { + throw Utils.rSuicide(msg); + } else { + throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, msg); + } } if (embedded) { consoleHandler = new EmbeddedConsoleHandler(rsp); } else { boolean useReadLine = !rsp.getNoReadline(); if (useReadLine) { - consoleHandler = new JLineConsoleHandler(rsp); + consoleHandler = new JLineConsoleHandler(rsp, inStream, outStream); } else { - consoleHandler = new DefaultConsoleHandler(System.in, System.out); + consoleHandler = new DefaultConsoleHandler(inStream, outStream); } } } - return ContextInfo.create(rsp, ContextKind.SHARE_NOTHING, null, consoleHandler).createVM(); + return ContextInfo.create(rsp, env, ContextKind.SHARE_NOTHING, initial ? null : RContext.getInstance(), consoleHandler).createVM(); } private static final Source GET_ECHO = RSource.fromTextInternal("invisible(getOption('echo'))", RSource.Internal.GET_ECHO); @@ -181,9 +200,10 @@ 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 void readEvalPrint(PolyglotEngine vm) { + static int readEvalPrint(PolyglotEngine vm) { int lastStatus = 0; - ConsoleHandler consoleHandler = ContextInfo.getContextInfo(vm).getConsoleHandler(); + ContextInfo contextInfo = ContextInfo.getContextInfo(vm); + ConsoleHandler consoleHandler = contextInfo.getConsoleHandler(); try { // console.println("initialize time: " + (System.currentTimeMillis() - start)); REPL: for (;;) { @@ -204,16 +224,18 @@ public class RCommand { StringBuffer sb = new StringBuffer(input); Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT); while (true) { - /* - * N.B. As of Truffle rev 371045b1312d412bafa29882e6c3f7bfe6c0f8f1, only - * exceptions that are <: Exception are converted to IOException, Error - * subclasses pass through. - */ lastStatus = 0; try { - vm.eval(source); - emitIO(); - } catch (IncompleteSourceException | com.oracle.truffle.api.vm.IncompleteSourceException e) { + try { + vm.eval(source); + // checked exceptions are wrapped in RuntimeExceptions + } catch (RuntimeException e) { + if (e.getCause() instanceof com.oracle.truffle.api.vm.IncompleteSourceException) { + throw e.getCause().getCause(); + } + throw e; + } + } catch (IncompleteSourceException e) { // read another line of input consoleHandler.setPrompt(doEcho ? continuePrompt : null); String additionalInput = consoleHandler.readLine(); @@ -226,27 +248,27 @@ public class RCommand { continue; } catch (ParseException e) { e.report(consoleHandler); - } catch (IOException e) { - /* - * We have to extract the underlying cause and handle the special cases - * appropriately. - */ lastStatus = 1; - Throwable cause = e.getCause(); - if (cause instanceof RError) { - // drop through to continue REPL and remember last eval was an error - } else if (cause instanceof JumpToTopLevelException) { - // drop through to continue REPL - } else if (cause instanceof DebugExitException) { - throw (RuntimeException) cause; - } else if (cause instanceof ExitException) { - // usually from quit + } catch (RError e) { + // drop through to continue REPL and remember last eval was an error + lastStatus = 1; + } catch (JumpToTopLevelException e) { + // drop through to continue REPL + } catch (DebugExitException e) { + throw (RuntimeException) e.getCause(); + } catch (ExitException e) { + // usually from quit + int status = e.getStatus(); + if (contextInfo.getParent() == null) { vm.dispose(); - System.exit(((ExitException) cause).getStatus()); + Utils.systemExit(status); } else { - RInternalError.reportErrorAndConsoleLog(cause, consoleHandler, 0); - // We continue the repl even though the system may be broken + return status; } + } catch (Throwable e) { + RInternalError.reportErrorAndConsoleLog(e, consoleHandler, 0); + // We continue the repl even though the system may be broken + lastStatus = 1; } continue REPL; } @@ -254,47 +276,43 @@ public class RCommand { // interrupted by ctrl-c } } - } catch (JumpToTopLevelException e) { - // can happen if user profile invokes browser (unlikely but possible) - } catch (EOFException ex) { + } catch (JumpToTopLevelException | EOFException ex) { + // JumpToTopLevelException can happen if user profile invokes browser (unlikely but + // possible) try { vm.eval(QUIT_EOF); - } catch (Throwable e) { - if (e.getCause() instanceof ExitException) { - // normal quit, but with exit code based on lastStatus - System.exit(lastStatus); + } catch (JumpToTopLevelException e) { + Utils.systemExit(0); + } catch (ExitException e) { + // normal quit, but with exit code based on lastStatus + if (contextInfo.getParent() == null) { + Utils.systemExit(lastStatus); + } else { + return lastStatus; } + } catch (Throwable e) { throw RInternalError.shouldNotReachHere(e); } } finally { vm.dispose(); } + return 0; } private static boolean doEcho(PolyglotEngine vm) { - PolyglotEngine.Value echoValue; - try { - echoValue = vm.eval(GET_ECHO); - emitIO(); - Object echo = echoValue.get(); - if (echo instanceof TruffleObject) { - RLogicalVector echoVec = echoValue.as(RLogicalVector.class); - return RRuntime.fromLogical(echoVec.getDataAt(0)); - } else if (echo instanceof Byte) { - return RRuntime.fromLogical((Byte) echo); - } else { - throw RInternalError.shouldNotReachHere(); - } - } catch (IOException e) { - throw RInternalError.shouldNotReachHere(e); + PolyglotEngine.Value echoValue = vm.eval(GET_ECHO); + Object echo = echoValue.get(); + if (echo instanceof TruffleObject) { + RLogicalVector echoVec = echoValue.as(RLogicalVector.class); + return RRuntime.fromLogical(echoVec.getDataAt(0)); + } else if (echo instanceof Byte) { + return RRuntime.fromLogical((Byte) echo); + } else { + throw RInternalError.shouldNotReachHere(); } } private static String getContinuePrompt() { return RRuntime.asString(RRuntime.asAbstractVector(RContext.getInstance().stateROptions.getValue("continue"))); } - - @SuppressWarnings("unused") - private static void emitIO() throws IOException { - } } 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 c4a0903de44e7231885b14bfc2dcfb98a58a58e2..1891e67ee86527391bec13005ac0d1e67ce8e588 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 @@ -22,13 +22,12 @@ */ package com.oracle.truffle.r.engine.shell; -import java.io.IOException; - import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.r.runtime.RCmdOptions; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RSource; +import com.oracle.truffle.r.runtime.RSource.Internal; import com.oracle.truffle.r.runtime.RStartParams; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.context.ContextInfo; @@ -70,16 +69,17 @@ public class REmbedded { private static PolyglotEngine initializeR(String[] args) { RContext.setEmbedded(); RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, true); - PolyglotEngine vm = RCommand.createPolyglotEngineFromCommandLine(options, true); - try { - vm.eval(INIT); - } catch (IOException ex) { - Utils.rSuicideDefault("initializeR"); - } + PolyglotEngine vm = RCommand.createPolyglotEngineFromCommandLine(options, true, true, System.in, System.out, null); + vm.eval(INIT); return vm; } - private static final Source INIT = RSource.fromTextInternal("1", RSource.Internal.GET_ECHO); + /** + * N.B. This expression cannot contain any R functions, e.g. "invisible", because at the time it + * is evaluated the R builtins have not been installed, see {@link #initializeR}. The + * suppression of printing is handled a a special case based on {@link Internal#INIT_EMBEDDED}. + */ + private static final Source INIT = RSource.fromTextInternal("1", RSource.Internal.INIT_EMBEDDED); /** * GnuR distinguishes {@code setup_Rmainloop} and {@code run_Rmainloop}. Currently we don't have 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 300f52e8acdf1ff2ae261947351ff9ba36d515bc..1af3eff3eb6a6efbacccde9875bac1e9b928a5de 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 @@ -29,6 +29,8 @@ import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_RESTORE; import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.SLAVE; import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.VERSION; +import java.io.InputStream; +import java.io.OutputStream; import java.util.ArrayList; import com.oracle.truffle.api.vm.PolyglotEngine; @@ -97,17 +99,23 @@ public class RscriptCommand { } public static void main(String[] args) { + doMain(args, null, true, System.in, System.out); + // never returns + throw RInternalError.shouldNotReachHere(); + } + + public static int doMain(String[] args, String[] env, boolean initial, InputStream inStream, OutputStream outStream) { // Since many of the options are shared parse them from an RSCRIPT perspective. // 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); - // never returns - RCommand.readEvalPrint(vm); - throw RInternalError.shouldNotReachHere(); + PolyglotEngine vm = RCommand.createPolyglotEngineFromCommandLine(options, false, initial, inStream, outStream, env); + return RCommand.readEvalPrint(vm); + } private static void printVersionAndExit() { + // TODO Not ok in nested context System.out.print("R scripting front-end version "); System.out.println(RVersionNumber.FULL); System.exit(0); 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 e2edc533d17467e02b41229e6293bc86c379f220..60af1f537c607a7152802ea422b86f8dd4459c78 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.engine.shell; +import java.io.OutputStream; import java.io.PrintStream; import java.util.List; @@ -35,9 +36,9 @@ class StringConsoleHandler implements ConsoleHandler { private String prompt; private int currentLine; - StringConsoleHandler(List<String> lines, PrintStream output, String inputDescription) { + StringConsoleHandler(List<String> lines, OutputStream output, String inputDescription) { this.lines = lines; - this.output = output; + this.output = output instanceof PrintStream ? (PrintStream) output : new PrintStream(output); this.inputDescription = inputDescription; } 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 index 93981c3efb05292f0a6af5dfe8327ebc5eed3a20..a8baa1e76adff364388f43b6886798a4c25d58b7 100644 --- 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.library.grid; +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.RArgsValuesAndNames; @@ -34,6 +35,7 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory; public class GridFunctions { public abstract static class InitGrid extends RExternalBuiltinNode.Arg1 { @Specialization + @TruffleBoundary protected Object initGrid(REnvironment gridEvalEnv) { return RFFIFactory.getRFFI().getGridRFFI().initGrid(gridEvalEnv); } @@ -41,6 +43,7 @@ public class GridFunctions { public static final class KillGrid extends RExternalBuiltinNode { @Override + @TruffleBoundary public Object call(RArgsValuesAndNames args) { return RFFIFactory.getRFFI().getGridRFFI().killGrid(); } 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 682b91fa607cef84a868fd069418f2b0e9bef573..dcbabcd63b5098130a999ff7a87fe52ea7eef6f5 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 @@ -128,7 +128,7 @@ public class MethodsListDispatch { @SuppressWarnings("unused") @Fallback - protected Object callGetClassFromCache(Object klass, REnvironment table) { + protected Object callGetClassFromCache(Object klass, Object table) { throw RError.error(this, RError.Message.GENERIC, "class should be either a character-string name or a class definition"); } } 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 d4662376be1fe55ff7b49a17877d61e4795a7a71..201f0d7d149f0946c17019e73cdccd860f6f9cc5 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 @@ -22,6 +22,7 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastToAttributableNode; import com.oracle.truffle.r.nodes.unary.CastToAttributableNodeGen; import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; // Transcribed from src/library/methods/slot.c @@ -34,7 +35,7 @@ public class Slot { @Child private CastToAttributableNode castAttributable = CastToAttributableNodeGen.create(true, true, true); protected static String getInternedName(RAbstractStringVector nameVec) { - return nameVec.getDataAt(0).intern(); + return Utils.intern(nameVec.getDataAt(0)); } @Specialization(guards = {"nameVec.getLength() == 1", "nameVec.getDataAt(0).equals(cachedInternedName)"}) @@ -44,7 +45,7 @@ public class Slot { @Specialization(contains = "getSlotCached", guards = "nameVec.getLength() == 1") protected Object getSlot(Object object, RAbstractStringVector nameVec) { - return accessSlotNode.executeAccess(castAttributable.executeObject(object), nameVec.getDataAt(0).intern()); + return accessSlotNode.executeAccess(castAttributable.executeObject(object), getInternedName(nameVec)); } @SuppressWarnings("unused") @@ -60,7 +61,7 @@ public class Slot { @Child private CastToAttributableNode castAttributable = CastToAttributableNodeGen.create(true, true, true); protected static String getInternedName(RAbstractStringVector nameVec) { - return nameVec.getDataAt(0).intern(); + return Utils.intern(nameVec.getDataAt(0)); } @Specialization(guards = {"nameVec.getLength() == 1", "nameVec.getDataAt(0).equals(cachedInternedName)"}) @@ -70,7 +71,7 @@ public class Slot { @Specialization(contains = "setSlotCached", guards = "nameVec.getLength() == 1") protected Object setSlot(Object object, RAbstractStringVector nameVec, Object value) { - return updateSlotNode.executeUpdate(castAttributable.executeObject(object), nameVec.getDataAt(0).intern(), value); + return updateSlotNode.executeUpdate(castAttributable.executeObject(object), getInternedName(nameVec), value); } @SuppressWarnings("unused") 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 549078a0834803cf50403222bb0ee88d451a7bd1..f8aaae671a57a121eeaea1f2edfefd714c2f0d5e 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 @@ -43,7 +43,7 @@ public abstract class SubstituteDirect extends RExternalBuiltinNode.Arg2 { protected static Object substituteDirect(Object object, REnvironment env) { if (object instanceof RLanguage) { RLanguage lang = (RLanguage) object; - return RASTUtils.createLanguageElement(RSubstitute.substitute(env, lang.getRep()).asRNode()); + return RASTUtils.createLanguageElement(RSubstitute.substitute(env, lang.getRep())); } else { return object; } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DPQ.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DPQ.java index 73496e65d7037f20c62a57192ceefe32b97e2aba..c033762f79c827e92511b4ef33ba34de874e2d4b 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DPQ.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DPQ.java @@ -156,7 +156,7 @@ public final class DPQ { // for discrete d<distr>(x, ...) : public static boolean dNonintCheck(double x) { if (nonint(x)) { - RError.warning(RError.SHOW_CALLER, Message.GENERIC, String.format("non-integer x = %f", x)); + RError.warning(RError.SHOW_CALLER, Message.NON_INTEGER_N, "x", x); return true; } return false; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/GammaFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/GammaFunctions.java index 5d7c44ece9c4e31149cdc8f0440680f9adc14610..556ee1c823258e2d1ae4cecd45a75bf2194e42a6 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/GammaFunctions.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/GammaFunctions.java @@ -689,9 +689,9 @@ public abstract class GammaFunctions { /* * PR# 2214 : From: Morten Welinder <terra@diku.dk>, Fri, 25 Oct 2002 16:50 -------- To: * R-bugs@biostat.ku.dk Subject: qgamma precision - * + * * With a final Newton step, double accuracy, e.g. for (p= 7e-4; nu= 0.9) - * + * * Improved (MM): - only if rel.Err > EPS_N (= 1e-15); - also for lower_tail = FALSE or * log_p = TRUE - optionally *iterate* Newton */ @@ -753,7 +753,7 @@ public abstract class GammaFunctions { /* * Continued fraction for calculation of 1/i + x/(i+d) + x^2/(i+2*d) + x^3/(i+3*d) + ... = * sum_{k=0}^Inf x^k/(i+k*d) - * + * * auxilary in log1pmx() and lgamma1p() */ private static double logcf(double x, double i, double d, double eps /* ~ relative tolerance */) { @@ -850,7 +850,7 @@ public abstract class GammaFunctions { * Abramowitz & Stegun 6.1.33 : for |x| < 2, <==> log(gamma(1+x)) = -(log(1+x) - x) - * gamma*x + x^2 * \sum_{n=0}^\infty c_n (-x)^n where c_n := (Zeta(n+2) - 1)/(n+2) = * coeffs[n] - * + * * Here, another convergence acceleration trick is used to compute lgam(x) := sum_{n=0..Inf} * c_n (-x)^n */ @@ -1076,17 +1076,17 @@ public abstract class GammaFunctions { /* * Compute the following ratio with higher accuracy that would be had from doing it directly. - * + * * dnorm (x, 0, 1, FALSE) ---------------------------------- pnorm (x, 0, 1, lower_tail, FALSE) - * + * * Abramowitz & Stegun 26.2.12 */ private static double dpnorm(double x, boolean lowerTail, double lp) { /* * So as not to repeat a pnorm call, we expect - * + * * lp == pnorm (x, 0, 1, lower_tail, TRUE) - * + * * but use it only in the non-critical case where either x is small or p==exp(lp) is close * to 1. */ @@ -1254,7 +1254,7 @@ public abstract class GammaFunctions { } } - private static double pgamma(double x, double alph, double scale, boolean lowerTail, boolean logp) { + public static double pgamma(double x, double alph, double scale, boolean lowerTail, boolean logp) { double localX = x; if (Double.isNaN(localX) || Double.isNaN(alph) || Double.isNaN(scale)) { return localX + alph + scale; @@ -1555,24 +1555,24 @@ public abstract class GammaFunctions { /* * 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.library/src/com/oracle/truffle/r/library/stats/Pbeta.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pbeta.java index 9143eb8205d7b1f53bb7b27b3a39757ea8c2cff4..4c950e6d35727e6fc3511907fc7f621500f399af 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pbeta.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pbeta.java @@ -54,11 +54,16 @@ public abstract class Pbeta extends RExternalBuiltinNode.Arg5 { // ==== /* ierr = 8 is about inaccuracy in extreme cases */ if (bratio.ierr != 0 && (bratio.ierr != 8 || logProb)) { - RError.warning(RError.SHOW_CALLER, Message.GENERIC, String.format("pbeta_raw(%g, a=%g, b=%g, ..) -> bratio() gave error code %d", x, a, b, bratio.ierr)); + doWarning(x, a, b, bratio.ierr); } return lowerTail ? bratio.w : bratio.w1; }/* pbeta_raw() */ + @TruffleBoundary + private static void doWarning(double x, double a, double b, int ierr) { + RError.warning(RError.SHOW_CALLER, Message.GENERIC, String.format("pbeta_raw(%g, a=%g, b=%g, ..) -> bratio() gave error code %d", x, a, b, ierr)); + } + static double pbeta(double x, double a, double b, boolean lowerTail, boolean logP, BranchProfile nanProfile) { if (Double.isNaN(x) || Double.isNaN(a) || Double.isNaN(b)) { nanProfile.enter(); diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pbinom.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pbinom.java index 5a224e7a0cd220eefad4909d0248f143718573df..2885a3c8b596d50c426db8664de8559088826846 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pbinom.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pbinom.java @@ -34,7 +34,7 @@ public final class Pbinom implements StatsFunctions.Function3_2 { if (DPQ.nonint(size)) { nanProfile.enter(); - RError.warning(RError.SHOW_CALLER, RError.Message.GENERIC, String.format("non-integer n = %f", size)); + RError.warning(RError.SHOW_CALLER, RError.Message.NON_INTEGER_N, "n", size); return Double.NaN; } size = Math.round(size); diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pf.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pf.java new file mode 100644 index 0000000000000000000000000000000000000000..51cf4f7e06d1f2833ce943b59dc2296041260add --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pf.java @@ -0,0 +1,72 @@ +/* + * 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) 1998 Ross Ihaka + * Copyright (c) 1998--2008, The R Core Team + * Copyright (c) 2016, 2016, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.stats; + +import static com.oracle.truffle.r.library.stats.StatsUtil.*; + +import com.oracle.truffle.api.profiles.BranchProfile; + +// transcribed from nmath/pf.c +public final class Pf implements StatsFunctions.Function3_2 { + + private final BranchProfile nanProfile = BranchProfile.create(); + + @Override + public double evaluate(double x, double df1, double df2, boolean lowerTail, boolean logP) { + if (Double.isNaN(x) || Double.isNaN(df1) || Double.isNaN(df2)) { + return x + df2 + df1; + } + + if (df1 <= 0 || df2 <= 0) { + // TODO ML_ERR_return_NAN + return Double.NaN; + } + + // expansion of R_P_bounds_01(x, 0., ML_POSINF); + if (x <= 0) { + return rdt0(lowerTail, logP); + } + if (x >= Double.POSITIVE_INFINITY) { + return rdt1(lowerTail, logP); + } + + if (df2 == Double.POSITIVE_INFINITY) { + if (df1 == Double.POSITIVE_INFINITY) { + if (x < 1) { + return rdt0(lowerTail, logP); + } + if (x == 1) { + return logP ? -M_LN2 : 0.5; + } + if (x > 1) { + return rdt1(lowerTail, logP); + } + } + + return GammaFunctions.pgamma(x * df1, df1 / 2, 2, lowerTail, logP); + } + + if (df1 == Double.POSITIVE_INFINITY) { + return GammaFunctions.pgamma(df2 / x, df2 / 2, 2, !lowerTail, logP); + } + + double ret; + if (df1 * x > df2) { + ret = Pbeta.pbeta(df2 / (df2 + df1 * x), df2 / 2, df1 / 2, !lowerTail, logP, nanProfile); + } else { + ret = Pbeta.pbeta(df1 * x / (df2 + df1 * x), df1 / 2, df2 / 2, lowerTail, logP, nanProfile); + } + + return ret; + + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rbinom.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rbinom.java index 288c55c5bfcdbb4e365694e95972cb22672750b9..74cf21b87fcb1104e4b3d67104eec9f6400a142c 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rbinom.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rbinom.java @@ -261,7 +261,9 @@ public abstract class Rbinom extends RExternalBuiltinNode.Arg3 { @Override protected void createCasts(CastBuilder casts) { - casts.toDouble(0).toDouble(1).toDouble(2); + casts.arg(0).asDoubleVector(); + casts.arg(1).asDoubleVector(); + casts.arg(2).asDoubleVector(); } @Specialization diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rnorm.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rnorm.java index 4e07b802a5632df442b9bed9d2693aa25ce2c332..d6c1c25102fd42f084fee09109a1f3e796c46b28 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rnorm.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rnorm.java @@ -33,8 +33,8 @@ public abstract class Rnorm extends RExternalBuiltinNode.Arg3 { @Override protected void createCasts(CastBuilder casts) { - casts.toDouble(1); - casts.toDouble(2); + casts.arg(1).asDoubleVector(); + casts.arg(2).asDoubleVector(); } @Specialization diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctions.java index 98b03fb580a2ac7b74c84deaf1447b644bef0ec5..033d9398750787d201d91e3ba289c0ef4afaf9c7 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctions.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctions.java @@ -12,6 +12,8 @@ */ package com.oracle.truffle.r.library.stats; +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.Node; @@ -99,7 +101,11 @@ public final class StatsFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.toDouble(0).toDouble(1).toDouble(2).firstBoolean(3).firstBoolean(4); + 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()); } @Specialization @@ -121,7 +127,10 @@ public final class StatsFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.toDouble(0).toDouble(1).toDouble(2).firstBoolean(3); + casts.arg(0).asDoubleVector(); + casts.arg(1).asDoubleVector(); + casts.arg(2).asDoubleVector(); + casts.arg(3).asLogicalVector().findFirst().map(toBoolean()); } @Specialization diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/TOMS708.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/TOMS708.java index 77aea95fdd0c872f46edca705b9f2a29f2088e6b..d1ddd7ab798fad0019530278e8c1fb32355175a2 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/TOMS708.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/TOMS708.java @@ -16,6 +16,7 @@ import static com.oracle.truffle.r.library.stats.MathConstants.M_LN_SQRT_2PI; import static com.oracle.truffle.r.library.stats.MathConstants.M_SQRT_PI; import static com.oracle.truffle.r.library.stats.MathConstants.logspaceAdd; +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.RInternalError; @@ -32,6 +33,7 @@ public class TOMS708 { // System.out.print(String.format(format, args)); } + @TruffleBoundary private static void emitWarning(String format, Object... args) { RError.warning(RError.SHOW_CALLER, Message.GENERIC, String.format(format, args)); } @@ -130,25 +132,25 @@ public class TOMS708 { public static Bratio bratio(double a, double b, double x, double y, boolean logP) { /* * ----------------------------------------------------------------------- - * + * * Evaluation of the Incomplete Beta function I_x(a,b) - * + * * -------------------- - * + * * It is assumed that a and b are nonnegative, and that x <= 1 and y = 1 - x. Bratio * assigns w and w1 the values - * + * * w = I_x(a,b) w1 = 1 - I_x(a,b) - * + * * ierr is a variable that reports the status of the results. If no input errors are * detected then ierr is set to 0 and w and w1 are computed. otherwise, if an error is * detected, then w and w1 are assigned the value 0 and ierr is set to one of the * following values ... - * + * * ierr = 1 if a or b is negative ierr = 2 if a = b = 0 ierr = 3 if x < 0 or x > 1 ierr * = 4 if y < 0 or y > 1 ierr = 5 if x + y != 1 ierr = 6 if x = a = 0 ierr = 7 if y = b * = 0 ierr = 8 "error" in bgrat() - * + * * -------------------- Written by Alfred H. Morris, Jr. Naval Surface Warfare Center * Dahlgren, Virginia Revised ... Nov 1991 * ----------------------------------------------------------------------- @@ -558,7 +560,7 @@ public class TOMS708 { * Expansion for I_x(a,b) when a is larger than b. Compute w := w + I_x(a,b) It is * assumed a >= 15 and b <= 1. eps is the tolerance used. ierr is a variable that * reports the status of the results. - * + * * if(log_w), *w itself must be in log-space; compute w := w + I_x(a,b) but return *w = * log(w): *w := log(exp(*w) + I_x(a,b)) = logspace_add(*w, log( I_x(a,b) )) * ----------------------------------------------------------------------- @@ -667,11 +669,11 @@ public class TOMS708 { private static double fpser(double a, double b, double x, double eps, boolean logP) { /* * ----------------------------------------------------------------------- * - * + * * EVALUATION OF I (A,B) X - * + * * FOR B < MIN(EPS, EPS*A) AND X <= 0.5 - * + * * ----------------------------------------------------------------------- */ @@ -1335,7 +1337,7 @@ public class TOMS708 { * ----------------------------------------------------------------------- Scaled complement * of incomplete gamma ratio function grat_r(a,x,r) := Q(a,x) / r where Q(a,x) = pgamma(x,a, * lower.tail=false) and r = e^(-x)* x^a / Gamma(a) == exp(log_r) - * + * * It is assumed that a <= 1. eps is the tolerance to be used. * ----------------------------------------------------------------------- */ @@ -1911,13 +1913,13 @@ public class TOMS708 { double x = initialX; /* * --------------------------------------------------------------------- - * + * * Evaluation of the Digamma function psi(x) - * + * * ----------- - * + * * Psi(xx) is assigned the value 0 when the digamma function cannot be computed. - * + * * The main computation involves evaluation of rational Chebyshev approximations published * in Math. Comp. 27, 123-127(1973) by Cody, Strecok and Thacher. */ diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/model.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/model.R index e0ebabafddce019be410544ca68bb4ccc6a5cf70..3245db800939dc6f30c42f3e67bee168579ac8ae 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/model.R +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/model.R @@ -494,21 +494,29 @@ TermCode <- function(formula, callIdx, varIndex) { } # gets the formula as parameter and returns the same formula, where -# dot symbol is replaced with (a+b+c+...) where a,b,c.. are framenames. -ExpandDots <- function(x) { +# the dot symbol is replaced with the 'replacement' +replaceDots <- function(x, replacement) { if (is.symbol(x)) { if (identical(x, quote(`.`))) { - return(parse(text=paste(framenames, collapse="+"))[[1]]) + return(replacement) } return(x) } for (i in seq_along(x)) { - x[[i]] <- ExpandDots(x[[i]]); + x[[i]] <- replaceDots(x[[i]], replacement); } x } +# gets the formula as parameter and returns the same formula, where +# the dot symbol is replaced with (a+b+c+...) where a,b,c.. are framenames. +# Note: this version is not equivalent of the GnuR C version as it expects +# variable names as the second argument. replaceDots is closer to the GnuR C version. +ExpandDots <- function(x, framenames) { + replaceDots(x, parse(text=paste(framenames, collapse="+"))[[1]]); +} + # PUBLIC: termsform # @@ -523,8 +531,10 @@ ExpandDots <- function(x) { # y 1 # "term.labels": y # "order", "intercept", "response": 1 -termsform <- function (x, specials, data, keep.order, allowDotAsName) { +termsform <- function (x.in, specials, data, keep.order, allowDotAsName) { + x <- x.in # make a copy, FastR invokes this without incrementing the ref-count for arguments + attributes(x) <- NULL if (!isLanguage(x) || !identical(x[[1]], quote(`~`)) || length(x) != 2L && length(x) != 3L) { @@ -647,8 +657,8 @@ termsform <- function (x, specials, data, keep.order, allowDotAsName) { if (nterm > 0L) { dimnames(pattern) <- list(varnames, termlabs) } - attr(x, "term.labels") <- termlabs attr(x, "factors") <- pattern + attr(x, "term.labels") <- termlabs if (!is.null(specials)) { specialsAttr <- vector("pairlist", length(specials)) @@ -666,13 +676,13 @@ termsform <- function (x, specials, data, keep.order, allowDotAsName) { # Step 6: Fix up the formula by substituting for dot, which should be # the framenames joined by + if (haveDot) { - x <- ExpandDots(x) + x <- ExpandDots(x, framenames) } attr(x, "order") <- ord attr(x, "intercept") <- as.integer(intercept) attr(x, "response") <- as.integer(response) - class(x) <- c("terms", "formula") + class(x) <- c("terms") return(x) } @@ -1247,6 +1257,43 @@ modelmatrix <- function(formula, modelframe) { x } +# ============================================================= +# Implementation of updateform +# PUBLIC updateform +# +# Replaces all occurences of dot symbol '.' in the lsh/rhs of 'new' formula with +# lhs/rhs of the 'old' formula. The result is stripped off of all attributes and +# gets .Environment attribute from the 'old' formula. +updateform <- function(old, new) { + is.formula <- function (x) is.language(x) && identical(x[[1L]], quote(`~`)); + if (!is.formula(old) || !is.formula(new)) { + error("formula expected") + } + if (length(old) == 3) { + lhs <- old[[2L]] + rhs <- old[[3L]] + # We now check that new formula has a valid lhs. If it doesn't, + # we add one and set it to the rhs of the old formula. + if (length(new) == 2) { + tmp <- new[[2L]] + new[[2L]] <- lhs + new[[3L]] <- tmp + } + # Note: we are probably getting away with not parenthesizing thanks to R + new[[2L]] <- replaceDots(new[[2L]], lhs) + new[[3L]] <- replaceDots(new[[3L]], rhs) + } else { + # the old formula has no lhs, we only expand rhs + if (length(new) == 3) { + new[[3L]] <- replaceDots(new[[3L]], old[[2L]]) + } else { + new[[2L]] <- replaceDots(new[[2L]], old[[2L]]) + } + } + attributes(new) <- NULL + attr(new, '.Environment') <- attr(old, '.Environment') + new +} 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 500935abcbbb319e31a5d33bbd6b9e9f0afbb8c5..f2e44f0a2f31d16d490898e7b07345d87f01b01e 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 @@ -24,6 +24,7 @@ package com.oracle.truffle.r.library.tools; import java.io.IOException; +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; @@ -49,6 +50,7 @@ public abstract class C_ParseRd extends RExternalBuiltinNode.Arg9 { return doParseRd(con, srcfile, encoding, verboseL, basename, fragmentL, warningCallsL, macros, warndupsL); } + @TruffleBoundary private Object doParseRd(RConnection con, REnvironment srcfile, @SuppressWarnings("unused") String encoding, byte verboseL, RAbstractStringVector basename, byte fragmentL, byte warningCallsL, Object macros, byte warndupsL) { if (RRuntime.isNA(warningCallsL)) { 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 1a3b5b635060055350eeda168b771f97a2b4cfa2..1e42cb01f00216e80f3a2ff768b76e02ac366dea 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 @@ -291,6 +291,7 @@ public final class CountFields extends RExternalBuiltinNode { // Transcribed from GnuR, library/utils/src/io.c @Override + @TruffleBoundary public Object call(RArgsValuesAndNames args) { Object[] argValues = args.getArguments(); RConnection conn = (RConnection) argValues[0]; 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 88292246a9de967261321f86fa5793cb93a198f6..722b28dacb17e478dd15c06ff250284630549682 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 @@ -28,6 +28,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; @@ -52,6 +53,7 @@ public final class Download extends RExternalBuiltinNode { } @Override + @TruffleBoundary public Integer call(RArgsValuesAndNames args) { Object[] argValues = args.getArguments(); String url = isString(argValues[0]); 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 13b4a88832dd2313a5c543cfc7576c4bc138c43f..cbfb8311a273bae3705e94b8d3f4e94a85ba7809 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 @@ -25,6 +25,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; public abstract class Menu extends RExternalBuiltinNode.Arg1 { @Specialization + @TruffleBoundary protected int menu(RAbstractStringVector choices) { ConsoleHandler ch = RContext.getInstance().getConsoleHandler(); int first = choices.getLength() + 1; 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 5b4d80c96f3f3d8b085cf7f2a706ebb056a7eba9..b952a0da7a3b74f43725f163a7221b7d57d48379 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,199 +22,56 @@ */ package com.oracle.truffle.r.library.utils; -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.library.utils.ObjectSizeNodeGen.RecursiveObjectSizeNodeGen; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; -import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode; -import com.oracle.truffle.r.runtime.data.RAttributable; -import com.oracle.truffle.r.runtime.data.RAttributes; -import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; -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.RObjectSize; 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.RNull; -import com.oracle.truffle.r.runtime.data.RPairList; -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.RTypedValue; -/* - * Similarly to GNU R's version, this is very approximate - * (e.g. overhead related to Java object headers is not included) - * and is only (semi) accurate for atomic vectors. +/** + * Similarly to GNU R's version, this is approximate and based, for {@link RTypedValue} instances on + * {@link RObjectSize#getObjectSize}. As per GNU R the AST size for a closure is included. TODO AST + * size not included owing to problems sizing it automatically. */ +@SuppressWarnings("unused") public abstract class ObjectSize extends RExternalBuiltinNode.Arg1 { - protected abstract int executeInt(Object o); - - @Child RecursiveObjectSize recursiveObjectSize; - - protected int recursiveObjectSize(Object o) { - if (recursiveObjectSize == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - recursiveObjectSize = insert(RecursiveObjectSizeNodeGen.create()); - } - return recursiveObjectSize.executeInt(o); - } - - @Specialization - protected int objectSize(@SuppressWarnings("unused") RNull o) { - return 64; // pointer? - } - - @Specialization - protected int objectSize(@SuppressWarnings("unused") int o) { - return 32; - } - - @Specialization - protected int objectSize(@SuppressWarnings("unused") double o) { - return 64; - } - - @Specialization - protected int objectSize(@SuppressWarnings("unused") byte o) { - return 8; - } - - @Specialization - protected int objectSize(String o) { - return o.length() * 16; - } - - @Specialization - protected int objectSize(@SuppressWarnings("unused") RRaw o) { - return 8; - } - - @Specialization - protected int objectSize(@SuppressWarnings("unused") RComplex o) { - return 128; - } - - @Specialization - protected int objectSize(RIntSequence o) { - int res = 96; // int length + int start + int stride - return res + attrSize(o); - } - - @Specialization - protected int objectSize(RDoubleSequence o) { - int res = 160; // int length + double start + double stride - return res + attrSize(o); - } - - @Specialization - protected int objectSize(RIntVector o) { - return o.getLength() * 32 + attrSize(o); - } - - @Specialization - protected int objectSize(RDoubleVector o) { - return o.getLength() * 64 + attrSize(o); - } - - @Specialization - protected int objectSize(RStringVector o) { - int res = 0; - for (int i = 0; i < o.getLength(); i++) { - res += o.getLength() * 16; - } - return res + attrSize(o); - } - - @Specialization - protected int objectSize(RLogicalVector o) { - return o.getLength() * 8 + attrSize(o); - } - - @Specialization - protected int objectSize(RComplexVector o) { - return o.getLength() * 128 + attrSize(o); - } - - @Specialization - protected int objectSize(RRawVector o) { - return o.getLength() * 8 + attrSize(o); - } - - @Specialization - @TruffleBoundary - protected int objectSize(RList o) { - int res = 0; - for (int i = 0; i < o.getLength(); i++) { - res += recursiveObjectSize(o.getDataAt(i)); - } - return res + attrSize(o); - } - - @Specialization - @TruffleBoundary - protected int objectSize(RPairList o) { - RPairList list = o; - Object car = list.car(); - int res = 0; - while (true) { - res += recursiveObjectSize(car); - Object cdr = list.cdr(); - if (cdr == RNull.instance) { - break; + private static class MyIgnoreObjectHandler implements RObjectSize.IgnoreObjectHandler { + @Override + public boolean ignore(Object rootObject, Object obj) { + if (obj == RNull.instance) { + return true; } else { - list = (RPairList) cdr; - car = list.car(); + return false; } } - return res + attrSize(o); - } - @Specialization - protected int objectSize(@SuppressWarnings("unused") RFunction o) { - return 256; // arbitrary, but does it really matter? } + private static final MyIgnoreObjectHandler ignoreObjectHandler = new MyIgnoreObjectHandler(); + @Specialization - protected int objectSize(@SuppressWarnings("unused") RLanguage o) { - return 256; // arbitrary, but does it really matter? + protected int objectSize(int o) { + return RObjectSize.INT_SIZE; } @Specialization - protected int objectSize(@SuppressWarnings("unused") RExpression o) { - return 256; // arbitrary, but does it really matter? + protected int objectSize(double o) { + return RObjectSize.DOUBLE_SIZE; } - protected int attrSize(RAttributable o) { - return o.getAttributes() == null ? 0 : attrSizeInternal(o.getAttributes()); + @Specialization + protected int objectSize(byte o) { + return RObjectSize.BYTE_SIZE; } + @Fallback @TruffleBoundary - protected int attrSizeInternal(RAttributes attributes) { - int size = 0; - for (RAttribute attr : attributes) { - size += attr.getName().length() * 16; - size += recursiveObjectSize(attr.getValue()); - } - return size; - } - - protected abstract static class RecursiveObjectSize extends TruffleBoundaryNode { - - protected abstract int executeInt(Object o); - - @Child ObjectSize objectSize = ObjectSizeNodeGen.create(); - - @Specialization - protected int objectSize(Object o) { - return objectSize.executeInt(o); - } + protected int objectSize(Object o) { + return (int) RObjectSize.getObjectSize(o, ignoreObjectHandler); } } 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 d03f663b1151eaae9a39bdecede4f62e9996a80e..5bb77e6214b8099938d01efdafee8e4a6b594697 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,9 +22,9 @@ */ package com.oracle.truffle.r.library.utils; -import java.io.FileWriter; +import java.io.FileOutputStream; import java.io.IOException; -import java.io.PrintWriter; +import java.io.PrintStream; import java.util.ArrayList; import java.util.HashMap; import java.util.function.Function; @@ -50,47 +50,69 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RObjectSize; +import com.oracle.truffle.r.runtime.data.RTypedValue; +import com.oracle.truffle.r.runtime.data.MemoryCopyTracer; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.instrument.InstrumentationState.RprofState; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.instrument.InstrumentationState; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; -public abstract class Rprof extends RExternalBuiltinNode.Arg8 { +/** + * Implements the {@code Rprof} external. + * + * The output is basically a sequence of call stacks, output at each sample interval, with entries + * in the stack identified by quoted function names. If memory profiling, the stack is preceded by a + * auad of numbers {@code :smallv:bigv:nodes:duplicate_counter:} allocated in the interval. If line + * profiling is enabled source files are listed as + * + * <pre> + * #File N: path + * </pre> + * + * and then the {@code N} is used in line number references of the form {@code N#L},which precede + * the function name. + * + */ +public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFactory.Listener, MemoryCopyTracer.Listener { @SuppressWarnings("unused") @Specialization + @TruffleBoundary public Object doRprof(RAbstractStringVector filenameVec, byte appendL, double intervalD, byte memProfilingL, byte gcProfilingL, byte lineProfilingL, int numFiles, int bufSize) { - if (!RContext.getInstance().isInitial()) { - throw RError.error(this, RError.Message.GENERIC, "profiling not supported in created contexts"); - } - RprofState profState = RContext.getInstance().stateInstrumentation.getRprof(); + RprofState profState = RprofState.get(); String filename = filenameVec.getDataAt(0); if (filename.length() == 0) { // disable endProfiling(); } else { - // enable - if (profState.out() != null) { + // enable after ending any previous session + if (profState != null && profState.out() != null) { endProfiling(); } boolean append = RRuntime.fromLogical(appendL); boolean memProfiling = RRuntime.fromLogical(memProfilingL); boolean gcProfiling = RRuntime.fromLogical(gcProfilingL); try { - PrintWriter out = new PrintWriter(new FileWriter(filename, append)); - if (memProfiling) { - RError.warning(this, RError.Message.GENERIC, "Rprof: memory profiling not supported"); - } + PrintStream out = new PrintStream(new FileOutputStream(filename, append)); if (gcProfiling) { RError.warning(this, RError.Message.GENERIC, "Rprof: gc profiling not supported"); } + if (memProfiling) { + RDataFactory.addListener(this); + RDataFactory.setTracingState(true); + MemoryCopyTracer.addListener(this); + MemoryCopyTracer.setTracingState(true); + } // interval is in seconds, we convert to millis long intervalInMillis = (long) (1E3 * intervalD); StatementListener statementListener = new StatementListener(); ProfileThread profileThread = new ProfileThread(intervalInMillis, statementListener); profileThread.setDaemon(true); - profState.initialize(out, profileThread, statementListener, intervalInMillis, RRuntime.fromLogical(lineProfilingL)); + profState.initialize(out, profileThread, statementListener, intervalInMillis, RRuntime.fromLogical(lineProfilingL), memProfiling); profileThread.start(); } catch (IOException ex) { throw RError.error(this, RError.Message.GENERIC, String.format("Rprof: cannot open profile file '%s'", filename)); @@ -99,48 +121,35 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 { return RNull.instance; } - private static void endProfiling() { - RprofState profState = RContext.getInstance().stateInstrumentation.getRprof(); - ProfileThread profileThread = (ProfileThread) profState.profileThread(); - profileThread.running = false; - HashMap<String, Integer> fileMap = null; - PrintWriter out = profState.out(); - StatementListener statementListener = (StatementListener) profState.statementListener(); - if (profState.lineProfiling()) { - out.print("line profiling: "); - } - out.printf("sample.interval=%d\n", profState.intervalInMillis() * 1000); - if (profState.lineProfiling()) { - // scan stacks to find files - fileMap = new HashMap<>(); - int fileIndex = 0; - for (ArrayList<RSyntaxNode> intervalStack : statementListener.intervalStacks) { - for (RSyntaxNode node : intervalStack) { - String path = getPath(node); - if (path != null && fileMap.get(path) == null) { - fileMap.put(path, ++fileIndex); - out.printf("#File %d: %s\n", fileIndex, path); - } - } + @Override + @TruffleBoundary + public void reportAllocation(RTypedValue data) { + RprofState profState = RprofState.get(); + long size = RObjectSize.getObjectSize(data, Rprofmem.myIgnoreObjectHandler); + if (data instanceof RAbstractVector) { + if (size >= Rprofmem.LARGE_VECTOR) { + profState.memoryQuad.largeV += size; + } else { + profState.memoryQuad.smallV += size; } + } else { + profState.memoryQuad.nodes += size; } - for (ArrayList<RSyntaxNode> intervalStack : statementListener.intervalStacks) { - for (RSyntaxNode node : intervalStack) { - RootNode rootNode = node.asRNode().getRootNode(); - if (rootNode instanceof FunctionDefinitionNode) { - String name = rootNode.getName(); - if (profState.lineProfiling()) { - Integer fileIndex = fileMap.get(getPath(node)); - if (fileIndex != null) { - out.printf("%d#%d ", fileIndex, node.getSourceSection().getStartLine()); - } - } - out.printf("\"%s\" ", name); - } - } - out.println(); + + } + + @Override + @TruffleBoundary + public void reportCopying(RAbstractVector source, RAbstractVector dest) { + RprofState profState = RprofState.get(); + profState.memoryQuad.copied += RObjectSize.getObjectSize(source, Rprofmem.myIgnoreObjectHandler); + } + + private static void endProfiling() { + RprofState profState = RprofState.get(); + if (profState.out() != null) { + profState.cleanup(0); } - out.close(); } private static String getPath(RSyntaxNode node) { @@ -177,8 +186,9 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 { * Emulates a sampling timer by checking when the sample interval rolls over and at that point * collects the stack of functions. */ - private static final class StatementListener implements ExecutionEventListener { + private final class StatementListener implements ExecutionEventListener { private ArrayList<ArrayList<RSyntaxNode>> intervalStacks = new ArrayList<>(); + private ArrayList<RprofState.MemoryQuad> intervalMemory = new ArrayList<>(); private volatile boolean newInterval; private StatementListener() { @@ -200,12 +210,17 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 { stack.add((RSyntaxNode) context.getInstrumentedNode()); collectStack(stack); intervalStacks.add(stack); + RprofState profState = RprofState.get(); + if (profState.memoryProfiling) { + intervalMemory.add(profState.memoryQuad.copyAndClear()); + } + newInterval = false; } } @TruffleBoundary - private static void collectStack(final ArrayList<RSyntaxNode> stack) { + private void collectStack(final ArrayList<RSyntaxNode> stack) { Utils.iterateRFrames(FrameAccess.READ_ONLY, new Function<Frame, Object>() { @Override @@ -233,4 +248,115 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 { } } + + /** + * State used by {@code Rprof}. + * + */ + private static final class RprofState extends InstrumentationState.RprofState { + private ProfileThread profileThread; + private StatementListener statementListener; + private long intervalInMillis; + private boolean lineProfiling; + private boolean memoryProfiling; + private MemoryQuad memoryQuad; + + public static final class MemoryQuad { + public long smallV; + public long largeV; + public long nodes; + public long copied; + + public MemoryQuad copyAndClear() { + MemoryQuad result = new MemoryQuad(); + result.copied = copied; + result.largeV = largeV; + result.smallV = smallV; + result.nodes = nodes; + copied = 0; + largeV = 0; + smallV = 0; + nodes = 0; + return result; + } + } + + private static RprofState get() { + RprofState state = (RprofState) RContext.getInstance().stateInstrumentation.getRprofState("prof"); + if (state == null) { + state = new RprofState(); + RContext.getInstance().stateInstrumentation.setRprofState("prof", state); + } + return state; + } + + public void initialize(PrintStream outA, ProfileThread profileThreadA, StatementListener statementListenerA, long intervalInMillisA, + boolean lineProfilingA, boolean memoryProfilingA) { + setOut(outA); + this.profileThread = profileThreadA; + this.statementListener = statementListenerA; + this.intervalInMillis = intervalInMillisA; + this.lineProfiling = lineProfilingA; + this.memoryProfiling = memoryProfilingA; + this.memoryQuad = memoryProfilingA ? new MemoryQuad() : null; + } + + @Override + public void cleanup(int status) { + profileThread.running = false; + HashMap<String, Integer> fileMap = null; + PrintStream out = this.out(); + if (this.memoryProfiling) { + out.print("memory profiling: "); + } + if (this.lineProfiling) { + out.print("line profiling: "); + } + out.printf("sample.interval=%d\n", this.intervalInMillis * 1000); + if (this.lineProfiling) { + // scan stacks to find files + fileMap = new HashMap<>(); + int fileIndex = 0; + for (ArrayList<RSyntaxNode> intervalStack : statementListener.intervalStacks) { + for (RSyntaxNode node : intervalStack) { + String path = getPath(node); + if (path != null && fileMap.get(path) == null) { + fileMap.put(path, ++fileIndex); + out.printf("#File %d: %s\n", fileIndex, path); + } + } + } + } + int index = 0; + for (ArrayList<RSyntaxNode> intervalStack : statementListener.intervalStacks) { + if (this.memoryProfiling) { + RprofState.MemoryQuad mq = statementListener.intervalMemory.get(index); + out.printf(":%d:%d:%d:%d:", mq.largeV, mq.smallV, mq.nodes, mq.copied); + } + for (RSyntaxNode node : intervalStack) { + RootNode rootNode = node.asRNode().getRootNode(); + if (rootNode instanceof FunctionDefinitionNode) { + String name = rootNode.getName(); + if (this.lineProfiling) { + Integer fileIndex = fileMap.get(getPath(node)); + if (fileIndex != null) { + out.printf("%d#%d ", fileIndex, node.getSourceSection().getStartLine()); + } + } + out.printf("\"%s\" ", name); + } + } + out.println(); + index++; + } + out.close(); + this.setOut(null); + if (this.memoryProfiling) { + RDataFactory.setTracingState(false); + MemoryCopyTracer.setTracingState(false); + } + + } + + } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..9708b8a15ea144246e4ab24bc74879036b442708 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprofmem.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2016, 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.utils; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +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.nodes.Node; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RTypedValue; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RObjectSize; +import com.oracle.truffle.r.runtime.data.RFunction; +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.instrument.InstrumentationState.RprofState; + +public abstract class Rprofmem extends RExternalBuiltinNode.Arg3 implements RDataFactory.Listener { + + @Specialization + @TruffleBoundary + public Object doRprofmem(RAbstractStringVector filenameVec, byte appendL, RAbstractDoubleVector thresholdVec) { + String filename = filenameVec.getDataAt(0); + if (filename.length() == 0) { + // disable + endProfiling(); + } else { + // enable after ending any previous session + RprofmemState profmemState = RprofmemState.get(); + if (profmemState != null && profmemState.out() != null) { + endProfiling(); + } + boolean append = RRuntime.fromLogical(appendL); + try { + PrintStream out = new PrintStream(new FileOutputStream(filename, append)); + profmemState.initialize(out, thresholdVec.getDataAt(0)); + 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)); + } + } + return RNull.instance; + } + + private static void endProfiling() { + RprofmemState profmemState = RprofmemState.get(); + if (profmemState.out() != null) { + profmemState.cleanup(0); + } + } + + private static final int PAGE_SIZE = 2000; + static final int LARGE_VECTOR = 128; + + /** + * We ignore nested {@link RTypedValue} instances as these will have been counted already. We + * also ignore {@link Node} instances, except in {@link RFunction} objects. + */ + private static class MyIgnoreObjectHandler implements RObjectSize.IgnoreObjectHandler { + @Override + public boolean ignore(Object rootObject, Object obj) { + if (obj == RNull.instance) { + return true; + } else { + Class<?> klass = obj.getClass(); + if (RTypedValue.class.isAssignableFrom(klass)) { + return true; + } else { + return false; + } + } + } + + } + + static final RObjectSize.IgnoreObjectHandler myIgnoreObjectHandler = new MyIgnoreObjectHandler(); + + @Override + @TruffleBoundary + public void reportAllocation(RTypedValue data) { + // We could do some in memory buffering + // TODO write out full stack + RprofmemState profmemState = RprofmemState.get(); + Frame frame = Utils.getActualCurrentFrame(); + if (frame == null) { + // not an R evaluation, some internal use + return; + } + RFunction func = RArguments.getFunction(frame); + if (func == null) { + return; + } + String name = func.getRootNode().getName(); + + long size = RObjectSize.getObjectSize(data, myIgnoreObjectHandler); + if (data instanceof RAbstractVector && size >= LARGE_VECTOR) { + if (size > profmemState.threshold) { + profmemState.out().printf("%d: %s\n", size, name); + } + } else { + int pageCount = profmemState.pageCount; + long pcs = pageCount + size; + if (pcs > PAGE_SIZE) { + profmemState.out().printf("new page: %s\n", name); + profmemState.pageCount = (int) (pcs - PAGE_SIZE); + } else { + profmemState.pageCount = (int) pcs; + } + } + + } + + private static final class RprofmemState extends RprofState { + private double threshold; + private int pageCount; + + private static RprofmemState get() { + RprofmemState state = (RprofmemState) RContext.getInstance().stateInstrumentation.getRprofState("mem"); + if (state == null) { + state = new RprofmemState(); + RContext.getInstance().stateInstrumentation.setRprofState("mem", state); + } + return state; + } + + public void initialize(PrintStream outA, double thresholdA) { + setOut(outA); + this.threshold = thresholdA; + } + + @Override + public void cleanup(int status) { + RDataFactory.setTracingState(false); + closeAndResetOut(); + } + } + +} 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 85156aa3395a71ef78d2c1ee1ab3f0ad18fcdc17..e856fd478387c79b96ea48c676b782656aa248d3 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 @@ -58,7 +58,7 @@ public abstract class TypeConvert extends RExternalBuiltinNode.Arg5 { private static RIntVector readIntVector(RAbstractStringVector x, int firstPos, int firstVal, RAbstractStringVector naStrings) { int[] data = new int[x.getLength()]; Arrays.fill(data, 0, firstPos, RRuntime.INT_NA); - boolean complete = RDataFactory.COMPLETE_VECTOR; + boolean complete = canBeComplete(firstPos); data[firstPos] = firstVal; for (int i = firstPos + 1; i < data.length; i++) { String s = x.getDataAt(i); @@ -72,7 +72,7 @@ public abstract class TypeConvert extends RExternalBuiltinNode.Arg5 { private static RDoubleVector readDoubleVector(RAbstractStringVector x, int firstPos, double firstVal, RAbstractStringVector naStrings) { double[] data = new double[x.getLength()]; Arrays.fill(data, 0, firstPos, RRuntime.DOUBLE_NA); - boolean complete = RDataFactory.COMPLETE_VECTOR; + boolean complete = canBeComplete(firstPos); data[firstPos] = firstVal; for (int i = firstPos + 1; i < data.length; i++) { String s = x.getDataAt(i); @@ -86,7 +86,7 @@ public abstract class TypeConvert extends RExternalBuiltinNode.Arg5 { private static RLogicalVector readLogicalVector(RAbstractStringVector x, int firstPos, byte firstVal, RAbstractStringVector naStrings) { byte[] data = new byte[x.getLength()]; Arrays.fill(data, 0, firstPos, RRuntime.LOGICAL_NA); - boolean complete = RDataFactory.COMPLETE_VECTOR; + boolean complete = canBeComplete(firstPos); data[firstPos] = firstVal; for (int i = firstPos + 1; i < data.length; i++) { String s = x.getDataAt(i); @@ -97,6 +97,10 @@ public abstract class TypeConvert extends RExternalBuiltinNode.Arg5 { return RDataFactory.createLogicalVector(data, complete); } + private static boolean canBeComplete(int firstNonNAPos) { + return firstNonNAPos == 0 ? RDataFactory.COMPLETE_VECTOR : RDataFactory.INCOMPLETE_VECTOR; + } + @Specialization protected Object typeConvert(RAbstractStringVector x, RAbstractStringVector naStrings, byte asIs, @SuppressWarnings("unused") Object dec, @SuppressWarnings("unused") Object numeral) { if (x.getLength() == 0) { @@ -104,7 +108,7 @@ public abstract class TypeConvert extends RExternalBuiltinNode.Arg5 { } int i = 0; - while (isNA(x.getDataAt(i), naStrings) && i < x.getLength()) { + while (i < x.getLength() && isNA(x.getDataAt(i), naStrings)) { i++; } diff --git a/com.oracle.truffle.r.native/Makefile b/com.oracle.truffle.r.native/Makefile index 0f209bf9e57b066c1072ed577eac1288d979e842..b56d8c118269f478873d72697f8fe47345bc71d6 100644 --- a/com.oracle.truffle.r.native/Makefile +++ b/com.oracle.truffle.r.native/Makefile @@ -33,14 +33,12 @@ export GNUR_HOME = $(TOPDIR)/gnur/R-$(R_VERSION) all: $(MAKE) -C gnur $(MAKE) -C include - $(MAKE) -C osextras $(MAKE) -C fficall $(MAKE) -C library $(MAKE) -C run clean: $(MAKE) -C include clean - $(MAKE) -C osextras clean $(MAKE) -C fficall clean $(MAKE) -C library clean $(MAKE) -C run clean diff --git a/com.oracle.truffle.r.native/fficall/Makefile b/com.oracle.truffle.r.native/fficall/Makefile index d703990b4fcac05314bb58a934cc567f10c57e2e..58b03709a572f46b7bf6c55934ba05f191ceb3dd 100644 --- a/com.oracle.truffle.r.native/fficall/Makefile +++ b/com.oracle.truffle.r.native/fficall/Makefile @@ -33,29 +33,48 @@ endif .PHONY: all clean objs -C_LIBNAME := libR$(DYLIB_EXT) -C_LIB := $(FASTR_LIB_DIR)/$(C_LIBNAME) +R_LIBNAME := libR$(DYLIB_EXT) +R_LIB := $(FASTR_LIB_DIR)/$(R_LIBNAME) +BOOTJNI_LIBNAME := libjniboot$(DYLIB_EXT) +BOOTJNI_LIB := $(FASTR_LIB_DIR)/$(BOOTJNI_LIBNAME) ifeq ($(OS_NAME), Darwin) VERSION_FLAGS := -current_version $(R_VERSION) -compatibility_version $(R_VERSION) endif BLAS_TARGET := $(FASTR_LIB_DIR)/libRblas$(DYLIB_EXT) +LAPACK_TARGET := $(FASTR_LIB_DIR)/libRlapack$(DYLIB_EXT) -all: $(C_LIB) +all: $(R_LIB) $(BOOTJNI_LIB) -$(C_LIB): objs - $(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(C_LIB) $(wildcard lib/*.o) -L $(GNUR_HOME)/lib -lRblas $(VERSION_FLAGS) +$(R_LIB): objs ifeq ($(OS_NAME),Darwin) - install_name_tool -change libRblas.dylib $(BLAS_TARGET) $(C_LIB) + $(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) + install_name_tool -change libRlapack.dylib @rpath/libRlapack.dylib $(R_LIB) + install_name_tool -id @rpath/libR.dylib $(R_LIB) +# check if we captured libpcre/libz, rpath those in libR + mx rupdatelib $(FASTR_LIB_DIR) +else + $(DYLIB_LD) $(DYLIB_LDFLAGS) -Wl,-rpath,'$$ORIGIN' -o $(R_LIB) $(wildcard lib/*.o) -L$(FASTR_LIB_DIR) -lRblas -lRlapack -lpcre -lz endif objs: $(MAKE) -C src/common all $(MAKE) -C src/jni all +$(BOOTJNI_LIB): bootobjs + $(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(BOOTJNI_LIB) src/jniboot/jniboot.o $(VERSION_FLAGS) +ifeq ($(OS_NAME),Darwin) + install_name_tool -id @rpath/libjniboot.dylib $(BOOTJNI_LIB) +endif + +bootobjs: + $(MAKE) -C src/jniboot all + clean: $(MAKE) -C src/common clean $(MAKE) -C src/jni clean - rm -rf $(C_LIB) + rm -rf $(R_LIB) + rm -rf $(BOOTJNI_LIB) diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Parse.c b/com.oracle.truffle.r.native/fficall/src/jni/Parse.c index 4727c2cba093be8d04f683e06f42b17eec0eed15..cc55518f197af736df1fedfb4780aea80643c0c4 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Parse.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Parse.c @@ -31,7 +31,7 @@ static jfieldID parseExprFieldID; void init_parse(JNIEnv *env) { parseMethodID = checkGetMethodID(env, CallRFFIHelperClass, "R_ParseVector", "(Ljava/lang/Object;ILjava/lang/Object;)Ljava/lang/Object;", 1); - parseResultClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper$ParseResult"); + parseResultClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper$ParseResult"); parseStatusFieldID = checkGetFieldID(env, parseResultClass, "parseStatus", "I", 0); parseExprFieldID = checkGetFieldID(env, parseResultClass, "expr", "Ljava/lang/Object;", 0); } 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 f0b05fc5733fe75249d9b14e5aaf0f1a35465176..b86229a115ec850ed2d81b4533c2efdd51a16cb7 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 @@ -29,7 +29,7 @@ static jmethodID findSymbolID; void init_dynload(JNIEnv *env) { DLLClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/DLL"); - JNI_PkgInitClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jnr/JNI_PkgInit"); + JNI_PkgInitClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit"); DotSymbolClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/DLL$DotSymbol"); RegisteredNativeSymbolClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/DLL$RegisteredNativeSymbol"); @@ -85,7 +85,7 @@ void R_RegisterCCallable(const char *package, const char *name, DL_FUNC fptr) { } JNIEXPORT jobject JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1PkgInit_setSymbol(JNIEnv *env, jclass c, jint nstOrd, jlong routinesAddr, jint index) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PkgInit_setSymbol(JNIEnv *env, jclass c, jint nstOrd, jlong routinesAddr, jint index) { const char *name; long fun; int numArgs; 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 61431ad1d6d0b6c2717a6d7d17d8babc84c26456..f7cb4401f5891fd9cfbcf9802c9b52f91c3dc10c 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c @@ -406,41 +406,61 @@ void setupOverrides(void) { } static void REmbed_nativeWriteConsole(JNIEnv *jniEnv, jclass c, jstring string, int otype) { - int len = (*jniEnv)->GetStringUTFLength(jniEnv, string); - const char *cbuf = (*jniEnv)->GetStringUTFChars(jniEnv, string, NULL); - if (ptr_R_WriteConsole == NULL) { - (*ptr_R_WriteConsoleEx)(cbuf, len, otype); - } else { - (*ptr_R_WriteConsole)(cbuf, len); + jmp_buf error_jmpbuf; + callEnter(jniEnv, &error_jmpbuf); + if (!setjmp(error_jmpbuf)) { + int len = (*jniEnv)->GetStringUTFLength(jniEnv, string); + const char *cbuf = (*jniEnv)->GetStringUTFChars(jniEnv, string, NULL); + if (ptr_R_WriteConsole == NULL) { + (*ptr_R_WriteConsoleEx)(cbuf, len, otype); + } else { + (*ptr_R_WriteConsole)(cbuf, len); + } + (*jniEnv)->ReleaseStringUTFChars(jniEnv, string, cbuf); } - (*jniEnv)->ReleaseStringUTFChars(jniEnv, string, cbuf); + callExit(jniEnv); } -JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nativeWriteConsole(JNIEnv *jniEnv, jclass c, jstring string) { +JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1REmbed_nativeWriteConsole(JNIEnv *jniEnv, jclass c, jstring string) { REmbed_nativeWriteConsole(jniEnv, c, string, 0); } -JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nativeWriteErrConsole(JNIEnv *jniEnv, jclass c, jstring string) { +JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1REmbed_nativeWriteErrConsole(JNIEnv *jniEnv, jclass c, jstring string) { REmbed_nativeWriteConsole(jniEnv, c, string, 1); } -JNIEXPORT jstring JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nativeReadConsole(JNIEnv *jniEnv, jclass c, jstring prompt) { - const char *cprompt = (*jniEnv)->GetStringUTFChars(jniEnv, prompt, NULL); - unsigned char cbuf[1024]; - int n = (*ptr_R_ReadConsole)(cprompt, cbuf, 1024, 0); - jstring result; - result = (*jniEnv)->NewStringUTF(jniEnv, (const char *)cbuf); - (*jniEnv)->ReleaseStringUTFChars(jniEnv, prompt, cprompt); +JNIEXPORT jstring JNICALL Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1REmbed_nativeReadConsole(JNIEnv *jniEnv, jclass c, jstring prompt) { + jmp_buf error_jmpbuf; + jstring result = NULL; + callEnter(jniEnv, &error_jmpbuf); + if (!setjmp(error_jmpbuf)) { + const char *cprompt = (*jniEnv)->GetStringUTFChars(jniEnv, prompt, NULL); + unsigned char cbuf[1024]; + int n = (*ptr_R_ReadConsole)(cprompt, cbuf, 1024, 0); + result = (*jniEnv)->NewStringUTF(jniEnv, (const char *)cbuf); + (*jniEnv)->ReleaseStringUTFChars(jniEnv, prompt, cprompt); + } + callExit(jniEnv); return result; } -JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nativeCleanUp(JNIEnv *jniEnv, jclass c, jint x, jint y, jint z) { +JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1REmbed_nativeCleanUp(JNIEnv *jniEnv, jclass c, jint x, jint y, jint z) { + jmp_buf error_jmpbuf; + callEnter(jniEnv, &error_jmpbuf); + if (!setjmp(error_jmpbuf)) { (*ptr_R_CleanUp)(x, y, z); + } + callExit(jniEnv); } -JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nativeSuicide(JNIEnv *jniEnv, jclass c, jstring string) { - const char *cbuf = (*jniEnv)->GetStringUTFChars(jniEnv, string, NULL); - (*ptr_R_Suicide)(cbuf); +JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1REmbed_nativeSuicide(JNIEnv *jniEnv, jclass c, jstring string) { + jmp_buf error_jmpbuf; + callEnter(jniEnv, &error_jmpbuf); + if (!setjmp(error_jmpbuf)) { + const char *cbuf = (*jniEnv)->GetStringUTFChars(jniEnv, string, NULL); + (*ptr_R_Suicide)(cbuf); + } + callExit(jniEnv); } void uR_PolledEvents(void) { @@ -581,16 +601,16 @@ CTXT R_getGlobalFunctionContext() { JNIEnv *jniEnv = getEnv(); jmethodID methodID = checkGetMethodID(jniEnv, CallRFFIHelperClass, "R_getGlobalFunctionContext", "()Ljava/lang/Object;", 1); CTXT result = (*jniEnv)->CallStaticObjectMethod(jniEnv, CallRFFIHelperClass, methodID); - result = checkRef(jniEnv, result); - return result == R_NilValue ? NULL : result; + SEXP new_result = checkRef(jniEnv, result); + return new_result == R_NilValue ? NULL : addGlobalRef(jniEnv, result, 0); } CTXT R_getParentFunctionContext(CTXT c) { JNIEnv *jniEnv = getEnv(); jmethodID methodID = checkGetMethodID(jniEnv, CallRFFIHelperClass, "R_getParentFunctionContext", "(Ljava/lang/Object;)Ljava/lang/Object;", 1); CTXT result = (*jniEnv)->CallStaticObjectMethod(jniEnv, CallRFFIHelperClass, methodID, c); - result = checkRef(jniEnv, result); - return result == R_NilValue ? NULL : result; + SEXP new_result = checkRef(jniEnv, result); + return new_result == R_NilValue ? NULL : addGlobalRef(jniEnv, result, 0); } SEXP R_getContextEnv(CTXT context) { @@ -627,3 +647,15 @@ int R_insideBrowser() { jmethodID methodID = checkGetMethodID(jniEnv, CallRFFIHelperClass, "R_insideBrowser", "()I", 1); return (*jniEnv)->CallStaticIntMethod(jniEnv, CallRFFIHelperClass, methodID); } + +int R_isGlobal(CTXT context) { + JNIEnv *jniEnv = getEnv(); + jmethodID methodID = checkGetMethodID(jniEnv, CallRFFIHelperClass, "R_isGlobal", "(Ljava/lang/Object;)I", 1); + return (*jniEnv)->CallStaticIntMethod(jniEnv, CallRFFIHelperClass, methodID, context); +} + +int R_isEqual(void* x, void* y) { + JNIEnv *jniEnv = getEnv(); + jmethodID methodID = checkGetMethodID(jniEnv, CallRFFIHelperClass, "R_isEqual", "(Ljava/lang/Object;Ljava/lang/Object;)I", 1); + return (*jniEnv)->CallStaticIntMethod(jniEnv, CallRFFIHelperClass, methodID, x, y); +} 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 14227cbd329b3acd95354e84d88609a379ecbaee..a5c4ac637f69b5193a979f241931a08f918a5da4 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c @@ -219,7 +219,7 @@ void init_internals(JNIEnv *env) { externalPtrSetTagMethodID = checkGetMethodID(env, RExternalPtrClass, "setTag", "(Ljava/lang/Object;)V", 0); externalPtrSetProtMethodID = checkGetMethodID(env, RExternalPtrClass, "setProt", "(Ljava/lang/Object;)V", 0); - CharSXPWrapperClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper$CharSXPWrapper"); + CharSXPWrapperClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper$CharSXPWrapper"); CharSXPWrapperContentsFieldID = checkGetFieldID(env, CharSXPWrapperClass, "contents", "Ljava/lang/String;", 0); R_computeIdenticalMethodID = checkGetMethodID(env, CallRFFIHelperClass, "R_computeIdentical", "(Ljava/lang/Object;Ljava/lang/Object;I)I", 1); @@ -252,24 +252,6 @@ SEXP Rf_ScalarReal(double value) { return checkRef(thisenv, result); } -// JNR calls to PCRE do not work properly (via JNR) without these wrappers - -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); - -char *fastr_pcre_maketables() { - return pcre_maketables(); -} - -void *fastr_pcre_compile(char * pattern, int options, char ** errorMessage, int *errOffset, char * tables) { - return pcre_compile(pattern, options, errorMessage, errOffset, tables); -} - -int fastr_pcre_exec(void * code, void *extra, char* subject, int subjectLength, int startOffset, int options, int *ovector, int ovecSize) { - return pcre_exec(code, extra, subject, subjectLength, startOffset, options, ovector, ovecSize); -} - SEXP Rf_ScalarString(SEXP value) { TRACE(TARGp, value); JNIEnv *thisenv = getEnv(); @@ -350,6 +332,7 @@ SEXP Rf_dimnamesgets(SEXP x, SEXP y) { SEXP Rf_eval(SEXP expr, SEXP env) { TRACE(TARGpp, expr, env); JNIEnv *thisenv = getEnv(); + updateNativeArrays(thisenv); SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, Rf_evalMethodID, expr, env); return checkRef(thisenv, result); } @@ -849,7 +832,7 @@ SEXP CADR(SEXP e) { } SEXP CDDR(SEXP e) { - TRACE(TARG1, e); + TRACE(TARGp, e); JNIEnv *thisenv = getEnv(); SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, CDDR_MethodID, e); return checkRef(thisenv, result); @@ -1455,6 +1438,7 @@ SEXP Rf_asS4(SEXP x, Rboolean b, int i) { static SEXP R_tryEvalInternal(SEXP x, SEXP y, int *ErrorOccurred, jboolean silent) { JNIEnv *thisenv = getEnv(); + updateNativeArrays(thisenv); jobject tryResult = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, R_tryEvalMethodID, x, y, silent); // If tryResult is NULL, an error occurred if (ErrorOccurred) { @@ -1526,7 +1510,7 @@ void R_SetExternalPtrTag(SEXP s, SEXP tag) { (*thisenv)->CallObjectMethod(thisenv, s, externalPtrSetTagMethodID, tag); } -void R_SetExternalPtrProt(SEXP s, SEXP p) { +void R_SetExternalPtrProtected(SEXP s, SEXP p) { JNIEnv *thisenv = getEnv(); (*thisenv)->CallObjectMethod(thisenv, s, externalPtrSetProtMethodID, p); } @@ -1609,12 +1593,13 @@ int R_check_class_etc (SEXP x, const char **valid) { return (int) unimplemented("R_check_class_etc"); } -void R_PreserveObject(SEXP x) { - // Not applicable +SEXP R_PreserveObject(SEXP x) { + // convert to a JNI global ref until explicitly released + return createGlobalRef(getEnv(), x, 0); } void R_ReleaseObject(SEXP x) { - // Not applicable + releaseGlobalRef(getEnv(), x); } void R_dot_Last(void) { diff --git a/com.oracle.truffle.r.native/fficall/src/jni/appl_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/appl_rffi.c new file mode 100644 index 0000000000000000000000000000000000000000..bd570ec5022b2a8a4703188087a92f611583e87a --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/jni/appl_rffi.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016, 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. + */ + +#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); + +JNIEXPORT void JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1RAppl_native_1dqrdc2(JNIEnv *env, jclass c, + jdoubleArray jx, jint ldx, jint n, jint p, jdouble tol, jintArray jrank, jdoubleArray jqraux, + jintArray jpivot, jdoubleArray jwork) { + double *x = (*env)->GetPrimitiveArrayCritical(env, jx, NULL); + int *rank = (*env)->GetPrimitiveArrayCritical(env, jrank, NULL); + double *qraux = (*env)->GetPrimitiveArrayCritical(env, jqraux, NULL); + int *pivot = (*env)->GetPrimitiveArrayCritical(env, jpivot, NULL); + double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL); + dqrdc2_(x, &ldx, &n, &p, &tol, rank, qraux, pivot, work); + (*env)->ReleasePrimitiveArrayCritical(env, jx, x, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jrank, rank, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jqraux, qraux, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jpivot, pivot, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jwork, work, 0); +} + +JNIEXPORT void JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1RAppl_native_1dqrcf(JNIEnv *env, jclass c, + jdoubleArray jx, jint n, jint k, jdoubleArray jqraux, jdoubleArray jy, jint ny, jdoubleArray jb, jintArray jinfo) { + double *x = (*env)->GetPrimitiveArrayCritical(env, jx, NULL); + double *qraux = (*env)->GetPrimitiveArrayCritical(env, jqraux, NULL); + double *y = (*env)->GetPrimitiveArrayCritical(env, jy, NULL); + double *b = (*env)->GetPrimitiveArrayCritical(env, jb, NULL); + int *info = (*env)->GetPrimitiveArrayCritical(env, jinfo, NULL); + dqrcf_(x, &n, &k, qraux, y, &ny, b, info); + (*env)->ReleasePrimitiveArrayCritical(env, jx, x, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jqraux, qraux, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jy, y, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jb, b, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jinfo, info, 0); +} + +JNIEXPORT void JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1RAppl_native_1dqrls(JNIEnv *env, jclass c, + jdoubleArray jx, int n, int p, jdoubleArray jy, int ny, double tol, jdoubleArray jb, + jdoubleArray jrsd, jdoubleArray jqty, jintArray jk, jintArray jjpvt, jdoubleArray jqraux, jdoubleArray jwork) { + double *x = (*env)->GetPrimitiveArrayCritical(env, jx, NULL); + double *y = (*env)->GetPrimitiveArrayCritical(env, jy, NULL); + double *b = (*env)->GetPrimitiveArrayCritical(env, jb, NULL); + double *rsd = (*env)->GetPrimitiveArrayCritical(env, jrsd, NULL); + double *qty = (*env)->GetPrimitiveArrayCritical(env, jqty, NULL); + int *k = (*env)->GetPrimitiveArrayCritical(env, jk, NULL); + int *jpvt = (*env)->GetPrimitiveArrayCritical(env, jjpvt, NULL); + double *qraux = (*env)->GetPrimitiveArrayCritical(env, jqraux, NULL); + double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL); + dqrls_(x, &n, &p, y, &ny, &tol, b, rsd, qty, k, jpvt, qraux, work); + (*env)->ReleasePrimitiveArrayCritical(env, jx, x, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jy, y, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jb, b, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jrsd, rsd, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jqty, qty, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jk, k, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jjpvt, jpvt, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jqraux, qraux, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jwork, work, 0); +} diff --git a/com.oracle.truffle.r.native/fficall/src/jni/base_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/base_rffi.c new file mode 100644 index 0000000000000000000000000000000000000000..0af58786b908555c60b933b7d7e42fb392c51a4d --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/jni/base_rffi.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2016, 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. + */ + +// JNI implementation of BaseRFFI + +#include <rffiutils.h> + +#include <sys/types.h> +#include <unistd.h> +#include <sys/stat.h> +#include <glob.h> +#include <sys/utsname.h> + +#include <errno.h> + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1getpid(JNIEnv *env, jclass c) { + pid_t pid = getpid(); + return (jint) pid; +} + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1getwd(JNIEnv *env, jclass c, jbyteArray jdest, int len) { + char *dest = (*env)->GetPrimitiveArrayCritical(env, jdest, NULL); + char *r = getcwd(dest, len); + if (r == NULL) return 0; + (*env)->ReleasePrimitiveArrayCritical(env, jdest, dest, 0); + return 1; +} + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1setwd(JNIEnv *env, jclass c, jstring jdir) { + const char *dir = (*env)->GetStringUTFChars(env, jdir, NULL); + int rc = chdir(dir); + (*env)->ReleaseStringUTFChars(env, jdir, dir); + return rc; +} + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1mkdtemp(JNIEnv *env, jclass c, jbyteArray jtemplate) { + char *template = (*env)->GetPrimitiveArrayCritical(env, jtemplate, NULL); + char *r = mkdtemp(template); + if (r == NULL) return 0; + (*env)->ReleasePrimitiveArrayCritical(env, jtemplate, template, 0); + return 1; +} + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1mkdir(JNIEnv *env, jclass c, jstring jdir, jint mode) { + const char *dir = (*env)->GetStringUTFChars(env, jdir, NULL); + int rc = mkdir(dir, mode); + (*env)->ReleaseStringUTFChars(env, jdir, dir); + return rc; +} + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1chmod(JNIEnv *env, jclass c, jstring jdir, jint mode) { + const char *dir = (*env)->GetStringUTFChars(env, jdir, NULL); + int rc = chmod(dir, mode); + (*env)->ReleaseStringUTFChars(env, jdir, dir); + return rc; +} + +JNIEXPORT jlong JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1strtol(JNIEnv *env, jclass c, jstring js, jint base, jintArray jerrno) { + const char *s = (*env)->GetStringUTFChars(env, js, NULL); + jlong rc = strtol(s, NULL, base); + if (errno) { + int *cerrno = (*env)->GetPrimitiveArrayCritical(env, jerrno, NULL); + *cerrno = errno; + (*env)->ReleasePrimitiveArrayCritical(env, jerrno, cerrno, 0); + } + (*env)->ReleaseStringUTFChars(env, js, s); + return rc; +} + +JNIEXPORT jstring JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1readlink(JNIEnv *env, jclass c, jstring jpath, jintArray jerrno) { + const char *path = (*env)->GetStringUTFChars(env, jpath, NULL); + char buf[4096]; + int len = readlink(path, buf, 4096); + jstring result = NULL; + if (len == -1) { + int *cerrno = (*env)->GetPrimitiveArrayCritical(env, jerrno, NULL); + *cerrno = errno; + (*env)->ReleasePrimitiveArrayCritical(env, jerrno, cerrno, 0); + } else { + buf[len] = 0; + result = (*env)->NewStringUTF(env, buf); + } + (*env)->ReleaseStringUTFChars(env, jpath, path); + return result; +} + + +static jmethodID addPathID = 0; + +JNIEXPORT void JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Glob_doglob(JNIEnv *env, jobject obj, jstring pattern) { + glob_t globstruct; + + if (addPathID == 0) { + addPathID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, obj), "addPath", "(Ljava/lang/String;)V"); + } + + const char *patternChars = (*env)->GetStringUTFChars(env, pattern, NULL); + int rc = glob(patternChars, 0, NULL, &globstruct); + if (rc == 0) { + int i; + for (i = 0; i < globstruct.gl_pathc; i++) { + char *path = globstruct.gl_pathv[i]; + jstring pathString = (*env)->NewStringUTF(env, path); + (*env)->CallVoidMethod(env, obj, addPathID, pathString); + } + } +} + +JNIEXPORT void JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UtsName_getutsname(JNIEnv *env, jobject obj) { + struct utsname name; + + uname(&name); + jstring sysname = (*env)->NewStringUTF(env, name.sysname); + jstring release = (*env)->NewStringUTF(env, name.release); + jstring version = (*env)->NewStringUTF(env, name.version); + jstring machine = (*env)->NewStringUTF(env, name.machine); + jstring nodename = (*env)->NewStringUTF(env, name.nodename); + + jclass klass = (*env)->GetObjectClass(env, obj); + + jfieldID sysnameId = checkGetFieldID(env, klass, "sysname", "Ljava/lang/String;", 0); + jfieldID releaseId = checkGetFieldID(env, klass, "release", "Ljava/lang/String;", 0); + jfieldID versionId = checkGetFieldID(env, klass, "version", "Ljava/lang/String;", 0); + jfieldID machineId = checkGetFieldID(env, klass, "machine", "Ljava/lang/String;", 0); + jfieldID nodenameId = checkGetFieldID(env, klass, "nodename", "Ljava/lang/String;", 0); + + (*env)->SetObjectField(env, obj, sysnameId, sysname); + (*env)->SetObjectField(env, obj, releaseId, release); + (*env)->SetObjectField(env, obj, versionId, version); + (*env)->SetObjectField(env, obj, machineId, machine); + (*env)->SetObjectField(env, obj, nodenameId, nodename); + +} diff --git a/com.oracle.truffle.r.native/fficall/src/jni/c_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/c_rffi.c new file mode 100644 index 0000000000000000000000000000000000000000..9f1015280a6f3e5edb4e47ff5e135564e6330422 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/jni/c_rffi.c @@ -0,0 +1,977 @@ +/* + * Copyright (c) 2016, 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. + */ + +#include <rffiutils.h> + +static jclass intArrayClass; +static jclass doubleArrayClass; + +void init_c(JNIEnv *env) { + intArrayClass = checkFindClass(env, "[I"); + doubleArrayClass = checkFindClass(env, "[D"); +} + +typedef void (*c0func)(); +typedef void (*c1func)(void *arg1); +typedef void (*c2func)(void *arg1, void *arg2); +typedef void (*c3func)(void *arg1, void *arg2, void *arg3); +typedef void (*c4func)(void *arg1, void *arg2, void *arg3, void *arg4); +typedef void (*c5func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5); +typedef void (*c6func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6); +typedef void (*c7func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7); +typedef void (*c8func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8); +typedef void (*c9func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9); +typedef void (*c10func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10); +typedef void (*c11func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11); +typedef void (*c12func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12); +typedef void (*c13func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13); +typedef void (*c14func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14); +typedef void (*c15func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15); +typedef void (*c16func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16); +typedef void (*c17func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17); +typedef void (*c18func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18); +typedef void (*c19func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19); +typedef void (*c20func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20); +typedef void (*c21func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21); +typedef void (*c22func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22); +typedef void (*c23func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23); +typedef void (*c24func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24); +typedef void (*c25func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25); +typedef void (*c26func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26); +typedef void (*c27func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27); +typedef void (*c28func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28); +typedef void (*c29func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29); +typedef void (*c30func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30); +typedef void (*c31func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31); +typedef void (*c32func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32); +typedef void (*c33func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33); +typedef void (*c34func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34); +typedef void (*c35func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35); +typedef void (*c36func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36); +typedef void (*c37func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37); +typedef void (*c38func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38); +typedef void (*c39func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39); +typedef void (*c40func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40); +typedef void (*c41func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41); +typedef void (*c42func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42); +typedef void (*c43func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43); +typedef void (*c44func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44); +typedef void (*c45func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45); +typedef void (*c46func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46); +typedef void (*c47func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47); +typedef void (*c48func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48); +typedef void (*c49func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49); +typedef void (*c50func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50); +typedef void (*c51func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50, void *arg51); +typedef void (*c52func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50, void *arg51, void *arg52); +typedef void (*c53func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50, void *arg51, void *arg52, void *arg53); +typedef void (*c54func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54); +typedef void (*c55func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55); +typedef void (*c56func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56); +typedef void (*c57func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56, + void *arg57); +typedef void (*c58func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56, + void *arg57, void *arg58); +typedef void (*c59func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56, + void *arg57, void *arg58, void *arg59); +typedef void (*c60func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56, + void *arg57, void *arg58, void *arg59, void *arg60); +typedef void (*c61func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56, + void *arg57, void *arg58, void *arg59, void *arg60, void *arg61); +typedef void (*c62func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56, + void *arg57, void *arg58, void *arg59, void *arg60, void *arg61, void *arg62); +typedef void (*c63func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56, + void *arg57, void *arg58, void *arg59, void *arg60, void *arg61, void *arg62, void *arg63); +typedef void (*c64func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56, + void *arg57, void *arg58, void *arg59, void *arg60, void *arg61, void *arg62, void *arg63, void *arg64); +typedef void (*c65func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, + void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16, + void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24, + void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32, + void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40, + void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48, + void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56, + void *arg57, void *arg58, void *arg59, void *arg60, void *arg61, void *arg62, void *arg63, void *arg64, + void *arg65); + + +JNIEXPORT void JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1C_c(JNIEnv *env, jclass c, jlong address, jobjectArray args) { + int len = (*env)->GetArrayLength(env, args); + void *cargs[len]; + jobject jarrays[len]; + for (int i = 0; i < len; i++) { + jarrays[i] = (*env)->GetObjectArrayElement(env, args, i); + cargs[i] = (*env)->GetPrimitiveArrayCritical(env, jarrays[i], NULL); + } + switch (len) { + case 0: { + c0func c0 = (c0func) address; + (*c0)(); + break; + } + + case 1: { + c1func c1 = (c1func) address; + (*c1)(cargs[0]); + break; + } + + case 2: { + c2func c2 = (c2func) address; + (*c2)(cargs[0], cargs[1]); + break; + } + + case 3: { + c3func c3 = (c3func) address; + (*c3)(cargs[0], cargs[1], cargs[2]); + break; + } + + case 4: { + c4func c4 = (c4func) address; + (*c4)(cargs[0], cargs[1], cargs[2], cargs[3]); + break; + } + + case 5: { + c5func c5 = (c5func) address; + (*c5)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4]); + break; + } + + case 6: { + c6func c6 = (c6func) address; + (*c6)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5]); + break; + } + + case 7: { + c7func c7 = (c7func) address; + (*c7)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6]); + break; + } + + case 8: { + c8func c8 = (c8func) address; + (*c8)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7]); + break; + } + + case 9: { + c9func c9 = (c9func) address; + (*c9)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8]); + break; + } + + case 10: { + c10func c10 = (c10func) address; + (*c10)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9]); + break; + } + + case 11: { + c11func c11 = (c11func) address; + (*c11)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10]); + break; + } + + case 12: { + c12func c12 = (c12func) address; + (*c12)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11]); + break; + } + + case 13: { + c13func c13 = (c13func) address; + (*c13)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12]); + break; + } + + case 14: { + c14func c14 = (c14func) address; + (*c14)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13]); + break; + } + + case 15: { + c15func c15 = (c15func) address; + (*c15)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14]); + break; + } + + case 16: { + c16func c16 = (c16func) address; + (*c16)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15]); + break; + } + + case 17: { + c17func c17 = (c17func) address; + (*c17)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16]); + break; + } + + case 18: { + c18func c18 = (c18func) address; + (*c18)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17]); + break; + } + + case 19: { + c19func c19 = (c19func) address; + (*c19)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18]); + break; + } + + case 20: { + c20func c20 = (c20func) address; + (*c20)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19]); + break; + } + + case 21: { + c21func c21 = (c21func) address; + (*c21)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20]); + break; + } + + case 22: { + c22func c22 = (c22func) address; + (*c22)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21]); + break; + } + + case 23: { + c23func c23 = (c23func) address; + (*c23)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22]); + break; + } + + case 24: { + c24func c24 = (c24func) address; + (*c24)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23]); + break; + } + + case 25: { + c25func c25 = (c25func) address; + (*c25)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24]); + break; + } + + case 26: { + c26func c26 = (c26func) address; + (*c26)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25]); + break; + } + + case 27: { + c27func c27 = (c27func) address; + (*c27)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26]); + break; + } + + case 28: { + c28func c28 = (c28func) address; + (*c28)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27]); + break; + } + + case 29: { + c29func c29 = (c29func) address; + (*c29)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28]); + break; + } + + case 30: { + c30func c30 = (c30func) address; + (*c30)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29]); + break; + } + + case 31: { + c31func c31 = (c31func) address; + (*c31)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30]); + break; + } + + case 32: { + c32func c32 = (c32func) address; + (*c32)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31]); + break; + } + + case 33: { + c33func c33 = (c33func) address; + (*c33)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32]); + break; + } + + case 34: { + c34func c34 = (c34func) address; + (*c34)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33]); + break; + } + + case 35: { + c35func c35 = (c35func) address; + (*c35)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34]); + break; + } + + case 36: { + c36func c36 = (c36func) address; + (*c36)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35]); + break; + } + + case 37: { + c37func c37 = (c37func) address; + (*c37)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36]); + break; + } + + case 38: { + c38func c38 = (c38func) address; + (*c38)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37]); + break; + } + + case 39: { + c39func c39 = (c39func) address; + (*c39)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38]); + break; + } + + case 40: { + c40func c40 = (c40func) address; + (*c40)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39]); + break; + } + + case 41: { + c41func c41 = (c41func) address; + (*c41)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40]); + break; + } + + case 42: { + c42func c42 = (c42func) address; + (*c42)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41]); + break; + } + + case 43: { + c43func c43 = (c43func) address; + (*c43)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42]); + break; + } + + case 44: { + c44func c44 = (c44func) address; + (*c44)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43]); + break; + } + + case 45: { + c45func c45 = (c45func) address; + (*c45)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44]); + break; + } + + case 46: { + c46func c46 = (c46func) address; + (*c46)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45]); + break; + } + + case 47: { + c47func c47 = (c47func) address; + (*c47)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46]); + break; + } + + case 48: { + c48func c48 = (c48func) address; + (*c48)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47]); + break; + } + + case 49: { + c49func c49 = (c49func) address; + (*c49)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48]); + break; + } + + case 50: { + c50func c50 = (c50func) address; + (*c50)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49]); + break; + } + + case 51: { + c51func c51 = (c51func) address; + (*c51)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49], cargs[50]); + break; + } + + case 52: { + c52func c52 = (c52func) address; + (*c52)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49], cargs[50], cargs[51]); + break; + } + + case 53: { + c53func c53 = (c53func) address; + (*c53)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49], cargs[50], cargs[51], cargs[52]); + break; + } + + case 54: { + c54func c54 = (c54func) address; + (*c54)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53]); + break; + } + + case 55: { + c55func c55 = (c55func) address; + (*c55)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54]); + break; + } + + case 56: { + c56func c56 = (c56func) address; + (*c56)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55]); + break; + } + + case 57: { + c57func c57 = (c57func) address; + (*c57)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55], + cargs[56]); + break; + } + + case 58: { + c58func c58 = (c58func) address; + (*c58)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55], + cargs[56], cargs[57]); + break; + } + + case 59: { + c59func c59 = (c59func) address; + (*c59)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55], + cargs[56], cargs[57], cargs[58]); + break; + } + + case 60: { + c60func c60 = (c60func) address; + (*c60)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55], + cargs[56], cargs[57], cargs[58], cargs[59]); + break; + } + + case 61: { + c61func c61 = (c61func) address; + (*c61)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55], + cargs[56], cargs[57], cargs[58], cargs[59], cargs[60]); + break; + } + + case 62: { + c62func c62 = (c62func) address; + (*c62)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55], + cargs[56], cargs[57], cargs[58], cargs[59], cargs[60], cargs[61]); + break; + } + + case 63: { + c63func c63 = (c63func) address; + (*c63)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55], + cargs[56], cargs[57], cargs[58], cargs[59], cargs[60], cargs[61], cargs[62]); + break; + } + + case 64: { + c64func c64 = (c64func) address; + (*c64)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55], + cargs[56], cargs[57], cargs[58], cargs[59], cargs[60], cargs[61], cargs[62], cargs[63]); + break; + } + + case 65: { + c65func c65 = (c65func) address; + (*c65)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7], + cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15], + cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23], + cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31], + cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39], + cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47], + cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55], + cargs[56], cargs[57], cargs[58], cargs[59], cargs[60], cargs[61], cargs[62], cargs[63], + cargs[64]); + break; + } + } + + for (int i = 0; i < len; i++) { + (*env)->ReleasePrimitiveArrayCritical(env, jarrays[i], cargs[i], 0); + } +} + diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rfficall.c b/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c similarity index 96% rename from com.oracle.truffle.r.native/fficall/src/jni/rfficall.c rename to com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c index a8d153d4a0c39265d82c94e63c739c61e1c7a777..e0628f0683fc7fd3da55ea830bd83ff26506a537 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/rfficall.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c @@ -26,7 +26,7 @@ #include <setjmp.h> JNIEXPORT void JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_initialize(JNIEnv *env, jclass c, +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_initialize(JNIEnv *env, jclass c, jobjectArray initialValues) { init_utils(env); // must be first init_variables(env, initialValues); @@ -35,14 +35,15 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_initialize(JNIEnv *env, init_rmath(env); init_random(env); init_parse(env); + init_pcre(env); + init_c(env); } JNIEXPORT void JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_nativeSetTempDir(JNIEnv *env, jclass c, jstring tempDir) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_nativeSetTempDir(JNIEnv *env, jclass c, jstring tempDir) { setTempDir(env, tempDir); } -static jmp_buf error_jmpbuf; // Boilerplate methods for the actual calls @@ -342,7 +343,8 @@ typedef SEXP (*call64func)(SEXP arg1, SEXP arg2, SEXP arg3, SEXP arg4, SEXP arg5 ); JNIEXPORT jobject JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call0(JNIEnv *env, jclass c, jlong address) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call0(JNIEnv *env, jclass c, jlong address) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -354,7 +356,8 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call0(JNIEnv *env, jclas } JNIEXPORT jobject JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call1(JNIEnv *env, jclass c, jlong address, jobject arg1) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call1(JNIEnv *env, jclass c, jlong address, jobject arg1) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -366,7 +369,8 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call1(JNIEnv *env, jclas } JNIEXPORT jobject JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call2(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call2(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -378,8 +382,9 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call2(JNIEnv *env, jclas } JNIEXPORT jobject JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call3(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call3(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, jobject arg3) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -391,21 +396,27 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call3(JNIEnv *env, jclas } JNIEXPORT jobject JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call4(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call4(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, jobject arg3, jobject arg4) { + jmp_buf error_jmpbuf; jobject result = NULL; + printf("in call4\n"); callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { call4func call4 = (call4func) address; + printf("calling\n"); result = (*call4)(checkRef(env, arg1), checkRef(env, arg2), checkRef(env, arg3), checkRef(env, arg4)); } + printf("callexit\n"); callExit(env); + printf("done\n"); return result; } JNIEXPORT jobject JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call5(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call5(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, jobject arg3, jobject arg4, jobject arg5) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -417,8 +428,9 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call5(JNIEnv *env, jclas } JNIEXPORT jobject JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call6(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call6(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, jobject arg3, jobject arg4, jobject arg5, jobject arg6) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -430,8 +442,9 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call6(JNIEnv *env, jclas } JNIEXPORT jobject JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call7(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call7(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, jobject arg3, jobject arg4, jobject arg5, jobject arg6, jobject arg7) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -443,8 +456,9 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call7(JNIEnv *env, jclas } JNIEXPORT jobject JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call8(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call8(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, jobject arg3, jobject arg4, jobject arg5, jobject arg6, jobject arg7, jobject arg8) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -456,8 +470,9 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call8(JNIEnv *env, jclas } JNIEXPORT jobject JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call9(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call9(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, jobject arg3, jobject arg4, jobject arg5, jobject arg6, jobject arg7, jobject arg8, jobject arg9) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -469,7 +484,8 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call9(JNIEnv *env, jclas } JNIEXPORT jobject JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call(JNIEnv *env, jclass c, jlong address, jobjectArray args) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call(JNIEnv *env, jclass c, jlong address, jobjectArray args) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); jsize len = (*env)->GetArrayLength(env, args); @@ -1213,7 +1229,8 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call(JNIEnv *env, jclass typedef void (*callVoid1func)(SEXP arg1); JNIEXPORT void JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_callVoid1(JNIEnv *env, jclass c, jlong address, jobject arg1) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_callVoid1(JNIEnv *env, jclass c, jlong address, jobject arg1) { + jmp_buf error_jmpbuf; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { callVoid1func call1 = (callVoid1func) address; @@ -1225,7 +1242,8 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_callVoid1(JNIEnv *env, j typedef void (*callVoid0func)(); JNIEXPORT void JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_callVoid0(JNIEnv *env, jclass c, jlong address) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_callVoid0(JNIEnv *env, jclass c, jlong address) { + jmp_buf error_jmpbuf; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { callVoid0func call1 = (callVoid0func) address; @@ -1237,7 +1255,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_callVoid0(JNIEnv *env, j #include <Rinterface.h> JNIEXPORT void JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_nativeSetInteractive(JNIEnv *env, jclass c, jboolean interactive) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_nativeSetInteractive(JNIEnv *env, jclass c, jboolean interactive) { R_Interactive = interactive; } 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 new file mode 100644 index 0000000000000000000000000000000000000000..f7e52ad62480baf634b92dfdd3b09e82195e15ab --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2016, 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. + */ + +#include <rffiutils.h> + +extern void ilaver_(int *major, int *minor, int *patch); + +JNIEXPORT void JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1ilaver(JNIEnv *env, jclass klass, jintArray jversion) { + int major; + int minor; + int patch; + ilaver_(&major, &minor, &patch); + int *version = (*env)->GetPrimitiveArrayCritical(env, jversion, NULL); + version[0] = major; + version[1] = minor; + version[2] = patch; + (*env)->ReleasePrimitiveArrayCritical(env, jversion, version, 0); +} + + +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); + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgeev(JNIEnv *env, jclass klass, + char jobVL, char jobVR, int n, jdoubleArray ja, int lda, jdoubleArray jwr, jdoubleArray jwi, jdoubleArray jvl, int ldvl, jdoubleArray jvr, int ldvr, jdoubleArray jwork, int lwork) { + double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL); + double *wr = (*env)->GetPrimitiveArrayCritical(env, jwr, NULL); + double *wi = (*env)->GetPrimitiveArrayCritical(env, jwi, NULL); + double *vl = jvl == NULL ? NULL : (*env)->GetPrimitiveArrayCritical(env, jvl, NULL); + double *vr = jvr == NULL ? NULL : (*env)->GetPrimitiveArrayCritical(env, jvr, NULL); + double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL); + int info; + dgeev_(&jobVL, &jobVR, &n, a, &lda, wr, wi, vl, &ldvl, vr, &ldvr, work, &lwork, &info); + (*env)->ReleasePrimitiveArrayCritical(env, ja, a, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jwr, wr, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jwi, wi, 0); + if (jvl != NULL) (*env)->ReleasePrimitiveArrayCritical(env, jvl, vl, 0); + if (jvr != NULL) (*env)->ReleasePrimitiveArrayCritical(env, jvr, vr, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jwork, work, 0); + return info; +} + +extern int dgeqp3_(int *m, int *n, double *a, int *lda, int *jpvt, double *tau, double *work, int *lwork, int *info); + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgeqp3(JNIEnv *env, jclass klass, + int m, int n, jdoubleArray ja, int lda, jintArray jjpvt, jdoubleArray jtau, jdoubleArray jwork, int lwork) { + double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL); + int *jpvt = (*env)->GetPrimitiveArrayCritical(env, jjpvt, NULL); + double *tau = (*env)->GetPrimitiveArrayCritical(env, jtau, NULL); + double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL); + int info; + dgeqp3_(&m, &n, a, &lda, jpvt, tau, work, &lwork, &info); + (*env)->ReleasePrimitiveArrayCritical(env, ja, a, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jjpvt, jpvt, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jtau, tau, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jwork, work, 0); + 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); + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dormqr(JNIEnv *env, jclass klass, + char side, char trans, int m, int n, int k, jdoubleArray ja, int lda, jdoubleArray jtau, jdoubleArray jc, int ldc, jdoubleArray jwork, int lwork) { + double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL); + double *tau = (*env)->GetPrimitiveArrayCritical(env, jtau, NULL); + double *c = (*env)->GetPrimitiveArrayCritical(env, jc, NULL); + double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL); + int info; + dormqr_(&side, &trans, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info); + (*env)->ReleasePrimitiveArrayCritical(env, ja, a, JNI_ABORT); + (*env)->ReleasePrimitiveArrayCritical(env, jtau, tau, JNI_ABORT); + (*env)->ReleasePrimitiveArrayCritical(env, jc, c, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jwork, work, 0); + 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); + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dtrtrs(JNIEnv *env, jclass klass, + char uplo, char trans, char diag, int n, int nrhs, jdoubleArray ja, int lda, jdoubleArray jb, int ldb) { + double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL); + double *b = (*env)->GetPrimitiveArrayCritical(env, jb, NULL); + int info; + dtrtrs_(&uplo, &trans, &diag, &n, &nrhs, a, &lda, b, &ldb, &info); + (*env)->ReleasePrimitiveArrayCritical(env, ja, a, JNI_ABORT); + (*env)->ReleasePrimitiveArrayCritical(env, jb, b, 0); + return info; +} + +extern int dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info); + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgetrf(JNIEnv *env, jclass klass, + int m, int n, jdoubleArray ja, int lda, jintArray jipiv) { + double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL); + int *ipiv = (*env)->GetPrimitiveArrayCritical(env, jipiv, NULL); + int info; + dgetrf_(&m, &n, a, &lda, ipiv, &info); + (*env)->ReleasePrimitiveArrayCritical(env, ja, a, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jipiv, ipiv, 0); + return info; +} + +extern int dpotrf_(char *uplo, int *n, double *a, int *lda, int *info); + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dpotrf(JNIEnv *env, jclass klass, + char uplo, int n, jdoubleArray ja, int lda) { + double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL); + int info; + dpotrf_(&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 +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dpstrf(JNIEnv *env, jclass klass, + char uplo, int n, jdoubleArray ja, int lda, jintArray jpiv, jintArray jrank, double tol, jdoubleArray jwork) { + double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL); + int *piv = (*env)->GetPrimitiveArrayCritical(env, jpiv, NULL); + int *rank = (*env)->GetPrimitiveArrayCritical(env, jrank, NULL); + double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL); + int info; + dpstrf_(&uplo, &n, a, &lda, piv, rank, &tol, work, &info); + (*env)->ReleasePrimitiveArrayCritical(env, ja, a, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jpiv, piv, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jrank, rank, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jwork, work, 0); + return info; +} + +extern int dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info); + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgesv(JNIEnv *env, jclass klass, + int n, int nrhs, jdoubleArray ja, int lda, jintArray jipiv, jdoubleArray jb, int ldb) { + double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL); + int *ipiv = (*env)->GetPrimitiveArrayCritical(env, jipiv, NULL); + double *b = (*env)->GetPrimitiveArrayCritical(env, jb, NULL); + int info; + dgesv_(&n, &nrhs, a, &lda, ipiv, b, &ldb, &info); + (*env)->ReleasePrimitiveArrayCritical(env, ja, a, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jipiv, ipiv, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jb, b, 0); + return info; +} + +extern double dlange_(char *norm, int *m, int *n, double *a, int *lda, double *work); + +JNIEXPORT jdouble JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dlange(JNIEnv *env, jclass klass, + char norm, int m, int n, jdoubleArray ja, int lda, jdoubleArray jwork) { + double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL); + double *work = jwork == NULL ? NULL : (*env)->GetPrimitiveArrayCritical(env, jwork, NULL); + double info = dlange_(&norm, &m, &n, a, &lda, work); + (*env)->ReleasePrimitiveArrayCritical(env, ja, a, JNI_ABORT); + if (jwork != NULL) (*env)->ReleasePrimitiveArrayCritical(env, jwork, work, JNI_ABORT); + return info; +} + +extern int dgecon_(char *norm, int *n, double *a, int *lda, double *anorm, double *rcond, double *work, int *iwork, int *info); + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgecon(JNIEnv *env, jclass klass, + char norm, int n, jdoubleArray ja, int lda, double anorm, jdoubleArray jrcond, jdoubleArray jwork, jintArray jiwork) { + double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL); + double *rcond = (*env)->GetPrimitiveArrayCritical(env, jrcond, NULL); + double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL); + int *iwork = (*env)->GetPrimitiveArrayCritical(env, jiwork, NULL); + int info; + dgecon_(&norm, &n, a, &lda, &anorm, rcond, work, iwork, &info); + (*env)->ReleasePrimitiveArrayCritical(env, ja, a, JNI_ABORT); + (*env)->ReleasePrimitiveArrayCritical(env, jrcond, rcond, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jwork, work, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jiwork, iwork, 0); + return info; +} + diff --git a/com.oracle.truffle.r.native/fficall/src/jni/misc_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/misc_rffi.c new file mode 100644 index 0000000000000000000000000000000000000000..b4ee639d1e7c9df1c303574cc9de1a4a060afed2 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/jni/misc_rffi.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015, 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. + */ + +#include <rffiutils.h> + +JNIEXPORT jdouble JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Misc_exactSumFunc(JNIEnv *env, jclass c, jdoubleArray values, jboolean hasNa, jboolean naRm) { + jint length = (*env)->GetArrayLength(env, values); + jdouble* contents = (jdouble*) (*env)->GetPrimitiveArrayCritical(env, values, NULL); + + 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++) { + jdouble value = contents[i]; + if (R_IsNA(value)) { + if (!naRm) { + (*env)->ReleasePrimitiveArrayCritical(env, values, contents, JNI_ABORT); + return R_NaReal; + } + } else { + sum += value; + } + } + + (*env)->ReleasePrimitiveArrayCritical(env, values, contents, JNI_ABORT); + return sum; +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..40819418b6236b84066ddb157c302cae90fdcfe6 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016, 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. + */ + +#include <rffiutils.h> + +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); + +jclass JNI_PCRE_ResultClass; +jmethodID ResultClassConstructorID; + +void init_pcre(JNIEnv *env) { + JNI_PCRE_ResultClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/PCRERFFI$Result"); + ResultClassConstructorID = checkGetMethodID(env, JNI_PCRE_ResultClass, "<init>", "(JLjava/lang/String;I)V", 0); +} + +JNIEXPORT jlong JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeMaketables(JNIEnv *env, jclass c) { + return (jlong) pcre_maketables(); +} + +JNIEXPORT jobject JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeCompile(JNIEnv *env, jclass c, jstring pattern, jint options, jlong tables) { + const char *patternChars = (*env)->GetStringUTFChars(env, pattern, NULL); + char *errorMessage; + int errOffset; + void *pcre_result = pcre_compile(patternChars, options, &errorMessage, &errOffset, (char*) tables); + jstring stringErrorMessage = NULL; + if (pcre_result == NULL) { + stringErrorMessage = (*env)->NewStringUTF(env, errorMessage); + } + jobject result = (*env)->NewObject(env, JNI_PCRE_ResultClass, ResultClassConstructorID, pcre_result, stringErrorMessage, errOffset); + return result; +} + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeExec(JNIEnv *env, jclass c,jlong code, jlong extra, jstring subject, + jint startOffset, jint options, jintArray ovector, jint ovectorLen) { + const char *subjectChars = (*env)->GetStringUTFChars(env, subject, NULL); + int subjectLength = (*env)->GetStringUTFLength(env, subject); + int* ovectorElems = (*env)->GetIntArrayElements(env, ovector, NULL); + + int rc = pcre_exec(code, extra, subjectChars, subjectLength, startOffset, options, + ovectorElems, ovectorLen); + (*env)->ReleaseIntArrayElements(env, ovector, ovectorElems, 0); + (*env)->ReleaseStringUTFChars(env, subject, subjectChars); + return rc; +} 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 43f13021a505226076c73c73e19162c98ce54186..c083d5a7811e31bc3d106fb65b55defeb8c4a6c8 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c @@ -43,14 +43,18 @@ jmethodID createSymbolMethodID; static jmethodID validateMethodID; static JNIEnv *curenv = NULL; -jmp_buf *callErrorJmpBuf; // default for trace output when enabled FILE *traceFile = NULL; -static int alwaysUseGlobal = 0; +typedef struct globalRefTable_struct { + int permanent; + SEXP gref; // The jobject (SEXP) global ref +} GlobalRefElem; + #define CACHED_GLOBALREFS_INITIAL_SIZE 64 -static SEXP *cachedGlobalRefs; +static GlobalRefElem *cachedGlobalRefs; +static int cachedGlobalRefsHwm; static int cachedGlobalRefsLength; // Data structure for managing the required copying of @@ -71,7 +75,7 @@ static NativeArrayElem *nativeArrayTable; // hwm of nativeArrayTable static int nativeArrayTableHwm; static int nativeArrayTableLength; -static void releaseNativeArray(JNIEnv *env, int index); +static void releaseNativeArray(JNIEnv *env, int index, int freedata); static int isEmbedded = 0; void setEmbedded() { @@ -79,10 +83,14 @@ void setEmbedded() { } // native down call depth, indexes nativeArrayTableHwmStack -int callDepth; +int callDepth = 0; + +#define CALLDEPTH_STACK_SIZE 16 +static int nativeArrayTableHwmStack[CALLDEPTH_STACK_SIZE]; + +// stack of jmp_buf ptrs for non-local control transfer on error +static jmp_buf* callErrorJmpBufTable[CALLDEPTH_STACK_SIZE]; -#define NATIVE_ARRAY_TABLE_HWM_STACK_SIZE 16 -int nativeArrayTableHwmStack[NATIVE_ARRAY_TABLE_HWM_STACK_SIZE] ; void init_utils(JNIEnv *env) { curenv = env; @@ -107,14 +115,15 @@ void init_utils(JNIEnv *env) { } } RDataFactoryClass = checkFindClass(env, "com/oracle/truffle/r/runtime/data/RDataFactory"); - CallRFFIHelperClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper"); + CallRFFIHelperClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper"); RRuntimeClass = checkFindClass(env, "com/oracle/truffle/r/runtime/RRuntime"); RInternalErrorClass = checkFindClass(env, "com/oracle/truffle/r/runtime/RInternalError"); unimplementedMethodID = checkGetMethodID(env, RInternalErrorClass, "unimplemented", "(Ljava/lang/String;)Ljava/lang/RuntimeException;", 1); createSymbolMethodID = checkGetMethodID(env, RDataFactoryClass, "createSymbolInterned", "(Ljava/lang/String;)Lcom/oracle/truffle/r/runtime/data/RSymbol;", 1); validateMethodID = checkGetMethodID(env, CallRFFIHelperClass, "validate", "(Ljava/lang/Object;)Ljava/lang/Object;", 1); - cachedGlobalRefs = calloc(CACHED_GLOBALREFS_INITIAL_SIZE, sizeof(SEXP)); + 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; @@ -134,8 +143,9 @@ const char *stringToChars(JNIEnv *jniEnv, jstring string) { void callEnter(JNIEnv *env, jmp_buf *jmpbuf) { setEnv(env); - callErrorJmpBuf = jmpbuf; - if (callDepth >= NATIVE_ARRAY_TABLE_HWM_STACK_SIZE) { + //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; @@ -143,27 +153,27 @@ void callEnter(JNIEnv *env, jmp_buf *jmpbuf) { } jmp_buf *getErrorJmpBuf() { - return callErrorJmpBuf; + // 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); + releaseNativeArray(env, i, 1); } nativeArrayTableHwm = oldHwm; callDepth--; } void invalidateNativeArray(JNIEnv *env, SEXP oldObj) { - int i; - for (i = 0; i < nativeArrayTableHwm; i++) { + for (int i = 0; i < nativeArrayTableHwm; i++) { NativeArrayElem cv = nativeArrayTable[i]; if ((*env)->IsSameObject(env, cv.obj, oldObj)) { #if TRACE_NATIVE_ARRAYS fprintf(traceFile, "invalidateNativeArray(%p): found\n", oldObj); #endif - releaseNativeArray(env, &cv); + releaseNativeArray(env, i, 1); nativeArrayTable[i].obj = NULL; } } @@ -172,6 +182,14 @@ void invalidateNativeArray(JNIEnv *env, SEXP oldObj) { #endif } +void updateNativeArrays(JNIEnv *env) { + int oldHwm = nativeArrayTableHwmStack[callDepth - 1]; + for (int i = oldHwm; i < nativeArrayTableHwm; i++) { + releaseNativeArray(env, i, 0); + } +} + + static void *findNativeArray(JNIEnv *env, SEXP x) { int i; for (i = 0; i < nativeArrayTableHwm; i++) { @@ -270,16 +288,16 @@ void *getNativeArray(JNIEnv *thisenv, SEXP x, SEXPTYPE type) { return data; } -static void releaseNativeArray(JNIEnv *env, int i) { +static void releaseNativeArray(JNIEnv *env, int i, int freedata) { NativeArrayElem cv = nativeArrayTable[i]; #if TRACE_NATIVE_ARRAYS - fprintf(traceFile, "releaseNativeArray(x=%p, ix=%d)\n", cv.obj, i); + fprintf(traceFile, "releaseNativeArray(x=%p, ix=%d, freedata=%d)\n", cv.obj, i, freedata); #endif if (cv.obj != NULL) { switch (cv.type) { case INTSXP: { jintArray intArray = (jintArray) cv.jArray; - (*env)->ReleaseIntArrayElements(env, intArray, (jint *)cv.data, 0); + (*env)->ReleaseIntArrayElements(env, intArray, (jint *)cv.data, freedata ? 0 : JNI_COMMIT); break; } @@ -293,78 +311,109 @@ static void releaseNativeArray(JNIEnv *env, int i) { internalData[i] = data[i] == NA_INTEGER ? 255 : (jbyte) data[i]; } (*env)->ReleaseByteArrayElements(env, byteArray, internalData, 0); - free(data); // was malloc'ed in addNativeArray + if (freedata){ + free(data); // was malloc'ed in addNativeArray + } break; } case REALSXP: { jdoubleArray doubleArray = (jdoubleArray) cv.jArray; - (*env)->ReleaseDoubleArrayElements(env, doubleArray, (jdouble *)cv.data, 0); + (*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, 0); + (*env)->ReleaseByteArrayElements(env, byteArray, (jbyte *)cv.data, freedata ? 0 : JNI_COMMIT); break; } default: fatalError("releaseNativeArray type"); } - // free up the slot - cv.obj = NULL; + if (freedata) { + // free up the slot + cv.obj = NULL; + } } } -static SEXP checkCachedGlobalRef(JNIEnv *env, SEXP obj, int useGlobal) { - int i; - for (i = 0; i < cachedGlobalRefsLength; i++) { - SEXP ref = cachedGlobalRefs[i]; - if (ref == NULL) { - break; +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, ref, obj)) { + if ((*env)->IsSameObject(env, elem.gref, obj)) { #if TRACE_REF_CACHE fprintf(traceFile, "gref: cache hit: %d\n", i); #endif - return ref; + return elem.gref; } } - SEXP result; - if (useGlobal) { - if (i >= cachedGlobalRefsLength) { - int newLength = cachedGlobalRefsLength * 2; + return NULL; +} + +SEXP addGlobalRef(JNIEnv *env, SEXP obj, int permanent) { + SEXP gref; + 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(SEXP)); - if (newCachedGlobalRefs == NULL) { - fatalError("FFI global refs table expansion failure"); - } - memcpy(newCachedGlobalRefs, cachedGlobalRefs, cachedGlobalRefsLength * sizeof(SEXP)); - free(cachedGlobalRefs); - cachedGlobalRefs = newCachedGlobalRefs; - cachedGlobalRefsLength = newLength; + SEXP newCachedGlobalRefs = calloc(newLength, sizeof(GlobalRefElem)); + if (newCachedGlobalRefs == NULL) { + fatalError("FFI global refs table expansion failure"); } - result = (*env)->NewGlobalRef(env, obj); - cachedGlobalRefs[i] = result; - } else { - result = obj; + memcpy(newCachedGlobalRefs, cachedGlobalRefs, cachedGlobalRefsLength * sizeof(GlobalRefElem)); + free(cachedGlobalRefs); + cachedGlobalRefs = newCachedGlobalRefs; + cachedGlobalRefsLength = newLength; } - return result; + 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; +#endif + cachedGlobalRefsHwm++; + return gref; } SEXP checkRef(JNIEnv *env, SEXP obj) { - SEXP result = checkCachedGlobalRef(env, obj, alwaysUseGlobal); - TRACE(TARGp, result); - return result; + SEXP gref = findCachedGlobalRef(env, obj); + TRACE(TARGpp, obj, global); + if (gref == NULL) { + return obj; + } else { + return gref; + } } -SEXP mkNamedGlobalRef(JNIEnv *env, SEXP obj) { - SEXP result = checkCachedGlobalRef(env, obj, 1); - return result; +SEXP createGlobalRef(JNIEnv *env, SEXP obj, int permanent) { + 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)) { +#if TRACE_REF_CACHE + fprintf(traceFile, "gref: release: index %d, gref: %p\n", i, elem.gref); +#endif + (*env)->DeleteGlobalRef(env, elem.gref); + cachedGlobalRefs[i].gref = NULL; + } + } } void validateRef(JNIEnv *env, SEXP x, const char *msg) { 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 62da16cdcf08af4579691d82e5b5d7b427c627f7..1a217b586c83a8ea42af363fa6adc2cb791dfc3d 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h +++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h @@ -46,10 +46,14 @@ void *unimplemented(char *msg); void fatalError(char *msg); // makes a call to the VM with x as an argument (for debugger validation) void validate(SEXP x); -// checks x against the list of canonical (named) refs, returning the canonical version if a match +// checks x against the list of global JNI refs, returning the global version if x matches (IsSameObject) SEXP checkRef(JNIEnv *env, SEXP x); -// creates a canonical (named) JNI global ref from x -SEXP mkNamedGlobalRef(JNIEnv *env, SEXP x); +// creates a global JNI global ref from x. If permanent is non-zero, calls to +// releaseGlobalRef are ignored and the global ref persists for the entire execution +// (used for the R global variables such as R_NilValue). +SEXP createGlobalRef(JNIEnv *env, SEXP x, int permanent); +// release a previously created JNI global ref +void releaseGlobalRef(JNIEnv *env, SEXP x); // validate a JNI reference void validateRef(JNIEnv *env, SEXP x, const char *msg); @@ -60,6 +64,7 @@ void callExit(JNIEnv *env); // called by callExit to deallocate transient memory void allocExit(); +// returns the jmp_buf at the current call depth jmp_buf *getErrorJmpBuf(); // Given the x denotes an R vector type, return a pointer to @@ -68,6 +73,9 @@ 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); +void updateNativeArrays(JNIEnv *env); + +SEXP addGlobalRef(JNIEnv *env, SEXP obj, int permanent); void init_rmath(JNIEnv *env); void init_variables(JNIEnv *env, jobjectArray initialValues); @@ -76,6 +84,8 @@ void init_internals(JNIEnv *env); void init_random(JNIEnv *env); void init_utils(JNIEnv *env); void init_parse(JNIEnv *env); +void init_pcre(JNIEnv *env); +void init_c(JNIEnv *env); void setEmbedded(void); diff --git a/com.oracle.truffle.r.native/fficall/src/jni/stats_fft.c b/com.oracle.truffle.r.native/fficall/src/jni/stats_fft.c new file mode 100644 index 0000000000000000000000000000000000000000..4ed4a0dcf2474cf871d25907b58d5a460c3a9063 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/jni/stats_fft.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016, 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. + */ + +#include <rffiutils.h> + +typedef void (*fft_factor)(int n, int *pmaxf, int *pmaxp); +typedef Rboolean (*fft_work)(double *a, int nseg, int n, int nspn, int isn, + double *work, int *iwork); + +JNIEXPORT void JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Stats_native_1fft_1factor(JNIEnv *env, jclass c, jlong address, + jint n, jintArray jpmaxf, jintArray jpmaxp) { + fft_factor f = (fft_factor) address; + int *pmaxf = (*env)->GetPrimitiveArrayCritical(env, jpmaxf, NULL); + int *pmaxp = (*env)->GetPrimitiveArrayCritical(env, jpmaxp, NULL); + f(n, pmaxp, pmaxf); + (*env)->ReleasePrimitiveArrayCritical(env, jpmaxf, pmaxf, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jpmaxp, pmaxp, 0); +} + +JNIEXPORT int JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Stats_native_1fft_1work(JNIEnv *env, jclass c, jlong address, + jdoubleArray ja, int nseg, int n, int nsps, int isn, jdoubleArray jwork, jintArray jiwork) { + fft_work f = (fft_work) address; + double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL); + double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL); + int *iwork = (*env)->GetPrimitiveArrayCritical(env, jiwork, NULL); + int res = f(a, nseg, n, nsps, isn, work, iwork); + (*env)->ReleasePrimitiveArrayCritical(env, ja, a, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jwork, work, JNI_ABORT); + (*env)->ReleasePrimitiveArrayCritical(env, jiwork, iwork, JNI_ABORT); + return res; +} diff --git a/com.oracle.truffle.r.native/fficall/src/jni/userrng_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/userrng_rffi.c new file mode 100644 index 0000000000000000000000000000000000000000..a946f23f8b1f9fbcc72322e199a1103afe3649a8 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/jni/userrng_rffi.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016, 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. + */ + +#include <rffiutils.h> + +typedef void (*call_init)(int seed); +typedef double* (*call_rand)(void); +typedef int* (*call_nSeed)(void); +typedef int* (*call_seeds)(void); + +JNIEXPORT void JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_init(JNIEnv *env, jclass c, jlong address, jint seed) { + call_init f = (call_init) address; + f(seed); +} + +JNIEXPORT double JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_rand(JNIEnv *env, jclass c, jlong address) { + call_rand f = (call_rand) address; + double* dp = f(); + return *dp; +} + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_nSeed(JNIEnv *env, jclass c, jlong address) { + call_nSeed f = (call_nSeed) address; + int *pn = f(); + return *pn; +} + +JNIEXPORT void JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_seeds(JNIEnv *env, jclass c, jlong address, jintArray seedsArray) { + call_seeds f = (call_seeds) address; + int *pseeds = f(); + int seedslen = (*env)->GetArrayLength(env, seedsArray); + int *data = (*env)->GetIntArrayElements(env, seedsArray, NULL); + for (int i = 0; i < seedslen; i++) { + data[i] = pseeds[i]; + } + (*env)->ReleaseIntArrayElements(env, seedsArray, data, 0); +} 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 328b067bd7ec76b0c201480912bc57097a77b9ae..ca381df5e2e84d8b6568bca259034d09d8227244 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/variables.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/variables.c @@ -61,7 +61,8 @@ SEXP FASTR_NamespaceRegistry() { CTXT FASTR_GlobalContext() { JNIEnv *env = getEnv(); - return (*env)->CallStaticObjectMethod(env, CallRFFIHelperClass, getGlobalContextMethodID); + CTXT res = (*env)->CallStaticObjectMethod(env, CallRFFIHelperClass, getGlobalContextMethodID); + return addGlobalRef(env, res, 0); } void init_variables(JNIEnv *env, jobjectArray initialValues) { @@ -104,7 +105,7 @@ void init_variables(JNIEnv *env, jobjectArray initialValues) { } else if (strcmp(nameChars, "R_NaInt") == 0) { R_NaInt = (*env)->CallIntMethod(env, value, intValueMethodID); } else { - SEXP ref = mkNamedGlobalRef(env, value); + SEXP ref = createGlobalRef(env, value, 1); if (strcmp(nameChars, "R_EmptyEnv") == 0) { R_EmptyEnv = ref; } else if (strcmp(nameChars, "R_NilValue") == 0) { diff --git a/com.oracle.truffle.r.native/fficall/src/jni/zip_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/zip_rffi.c new file mode 100644 index 0000000000000000000000000000000000000000..e6bbec4c6cd08089bc7f3eea81a57198a064c21f --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/jni/zip_rffi.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016, 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. + */ + +#include <rffiutils.h> + +extern int compress(char *dest, long *destlen, char *source, long *sourcelen); +extern int uncompress(char *dest, long *destlen, char *source, long *sourcelen); + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Zip_native_1compress(JNIEnv *env, jclass c, + jbyteArray jdest, jlong destlen, jbyteArray jsource, jlong sourcelen) { + char *dest = (*env)->GetPrimitiveArrayCritical(env, jdest, NULL); + char *source = (*env)->GetPrimitiveArrayCritical(env, jsource, NULL); + int rc = compress(dest, &destlen, source, sourcelen); + (*env)->ReleasePrimitiveArrayCritical(env, jdest, dest, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jsource, source, JNI_ABORT); + return rc; +} + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Zip_native_1uncompress(JNIEnv *env, jclass c, + jbyteArray jdest, jlong destlen, jbyteArray jsource, jlong sourcelen) { + char *dest = (*env)->GetPrimitiveArrayCritical(env, jdest, NULL); + char *source = (*env)->GetPrimitiveArrayCritical(env, jsource, NULL); + int rc = uncompress(dest, &destlen, source, sourcelen); + (*env)->ReleasePrimitiveArrayCritical(env, jdest, dest, 0); + (*env)->ReleasePrimitiveArrayCritical(env, jsource, source, JNI_ABORT); + return rc; +} diff --git a/com.oracle.truffle.r.native/osextras/Makefile b/com.oracle.truffle.r.native/fficall/src/jniboot/Makefile similarity index 64% rename from com.oracle.truffle.r.native/osextras/Makefile rename to com.oracle.truffle.r.native/fficall/src/jniboot/Makefile index 3e88e01f22dc0f38867cc582bb6154dc180458c0..951610837a51d0497f2692f460b1cab72c99bbfb 100644 --- a/com.oracle.truffle.r.native/osextras/Makefile +++ b/com.oracle.truffle.r.native/fficall/src/jniboot/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2016, 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 @@ -21,38 +21,16 @@ # questions. # -ifeq ($(TOPDIR),) - TOPDIR = $(abspath ../..) -endif - ifneq ($(MAKECMDGOALS),clean) include $(TOPDIR)/platform.mk endif -.PHONY: all clean -OBJ = lib -SRC = src -C_SOURCES := $(wildcard $(SRC)/*.c) -C_LIBNAME := libosextras$(DYLIB_EXT) -C_OBJECTS := $(subst $(SRC),$(OBJ),$(C_SOURCES:.c=.o)) -C_LIB := $(TOPDIR)/../lib/$(C_LIBNAME) -#CFLAGS := $(CFLAGS) -DFASTR +.PHONY: all JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(JDK_OS_DIR) -INCLUDES := $(JNI_INCLUDES) - -all: $(C_LIB) - -$(C_LIB): $(OBJ) $(C_OBJECTS) - $(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(C_LIB) $(C_OBJECTS) - -$(OBJ): - mkdir -p $(OBJ) - -$(OBJ)/%.o: $(SRC)/%.c - $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ +all: jniboot.o -clean: - rm -rf $(OBJ) $(C_LIB) +jniboot.o: jniboot.c + $(CC) $(CFLAGS) $(JNI_INCLUDES) -c jniboot.c -o $@ diff --git a/com.oracle.truffle.r.native/fficall/src/jniboot/jniboot.c b/com.oracle.truffle.r.native/fficall/src/jniboot/jniboot.c new file mode 100644 index 0000000000000000000000000000000000000000..aa51df676458a614bfa25ee11fdc859701f0c33c --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/jniboot/jniboot.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016, 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. + */ + +// These functions, while defined in JNI_Base are stored in a seperate library, jniboot +// in order to be able to bootstrap the system as libR has to be loaded using these functions. + +#include <dlfcn.h> +#include <jni.h> + +// It seems that an internal (JVM) dlsym call can occur between a call to these functions and dlerror +// (probably resolving the JNI dlerror symbol, so we capture it here (N.B. depends on single +// threaded limitation). + +static jobject last_dlerror = NULL; + +static void create_dlerror_string(JNIEnv *env) { + if (last_dlerror != NULL) { + (*env)->DeleteGlobalRef(env, last_dlerror); + last_dlerror = NULL; + } + char *err = dlerror(); + if (err == NULL) { + last_dlerror = NULL; + } else { +// printf("dlerror: %s\n", err); + last_dlerror = (*env)->NewGlobalRef(env, (*env)->NewStringUTF(env, err)); + } +} + +JNIEXPORT jlong JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1dlopen(JNIEnv *env, jclass c, jstring jpath, jboolean local, jboolean now) { + const char *path = (*env)->GetStringUTFChars(env, jpath, NULL); + int flags = (local ? RTLD_LOCAL : RTLD_GLOBAL) | (now ? RTLD_NOW : RTLD_LAZY); + void *handle = dlopen(path, flags); + if (handle == NULL) { + create_dlerror_string(env); + } + (*env)->ReleaseStringUTFChars(env, jpath, path); + return (jlong) handle; +} + +JNIEXPORT jlong JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1dlsym(JNIEnv *env, jclass c, jlong handle, jstring jsymbol) { + const char *symbol = (*env)->GetStringUTFChars(env, jsymbol, NULL); + void *address = dlsym((void *)handle, symbol); + create_dlerror_string(env); + (*env)->ReleaseStringUTFChars(env, jsymbol, symbol); + return (jlong) address; +} + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1dlclose(JNIEnv *env, jclass c, jlong handle) { + int rc = dlclose((void *)handle); + return rc; +} + +JNIEXPORT jobject JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1dlerror(JNIEnv *env, jclass c) { + return last_dlerror; +} + diff --git a/com.oracle.truffle.r.native/gnur/Makefile.libs b/com.oracle.truffle.r.native/gnur/Makefile.libs index 13841dcc2b47ed3aeb80dc589d1f0422f010b9de..7463102b120cae57d288d254928172a2c100152e 100644 --- a/com.oracle.truffle.r.native/gnur/Makefile.libs +++ b/com.oracle.truffle.r.native/gnur/Makefile.libs @@ -33,8 +33,14 @@ endif BLAS_TARGET := $(FASTR_LIB_DIR)/libRblas$(DYLIB_EXT) LAPACK_TARGET := $(FASTR_LIB_DIR)/libRlapack$(DYLIB_EXT) +# at a minimum we need to know where libpcre/libz/libgfortran/libquadmath are located, +# to keep the Java side simpler, we (may) copy them to $(FASTR_LIB_DIR) unless +# they were found in the standard system locations +OTHER_LIB_TARGETS = pcre z gfortran quadmath gcc_s -all: $(FASTR_LIB_DIR) $(BLAS_TARGET) $(LAPACK_TARGET) +.PHONY: all other_lib_targets + +all: $(FASTR_LIB_DIR) $(BLAS_TARGET) $(LAPACK_TARGET) other_lib_targets $(FASTR_LIB_DIR): mkdir -p $(FASTR_LIB_DIR) @@ -45,13 +51,21 @@ $(BLAS_TARGET): $(GNUR_HOME)/lib/libRblas$(DYLIB_EXT) $(LAPACK_TARGET): $(GNUR_HOME)/lib/libRlapack$(DYLIB_EXT) cp $(GNUR_HOME)/lib/libRlapack$(DYLIB_EXT) $(LAPACK_TARGET) ifeq ($(OS_NAME),Darwin) - install_name_tool -change libRblas.dylib $(BLAS_TARGET) $(LAPACK_TARGET) - install_name_tool -change libR.dylib $(FASTR_LIB_DIR)/libR.dylib $(LAPACK_TARGET) - install_name_tool -id $(BLAS_TARGET) $(BLAS_TARGET) - install_name_tool -id $(LAPACK_TARGET) $(LAPACK_TARGET) +# libRblas depends on libgfortran, libquadmath +# libRlapack depends on libgfortran, libquadmath, libRblas, libR +# use @rpath to make references relocatable + install_name_tool -change libRblas.dylib @rpath/libRblas.dylib $(LAPACK_TARGET) + install_name_tool -change libR.dylib @rpath/libR.dylib $(LAPACK_TARGET) + install_name_tool -id @rpath/libRblas.dylib $(BLAS_TARGET) + install_name_tool -id @rpath/libRlapack.dylib $(LAPACK_TARGET) endif +other_lib_targets: + for target in $(OTHER_LIB_TARGETS); do \ + mx rcopylib $$target $(FASTR_LIB_DIR) || exit 1; \ + done + clean: - rm -f $(BLAS_TARGET) $(LAPACK_TARGET) + rm -f $(BLAS_TARGET) $(LAPACK_TARGET) + rm -f $(foreach target,$(OTHER_LIB_TARGETS),$(wildcard $(FASTR_LIB_DIR)/lib$(target).*)) - diff --git a/com.oracle.truffle.r.native/include/ed_Rinterface_gcntx b/com.oracle.truffle.r.native/include/ed_Rinterface_gcntx index f9cf0613c24ce9f66f6d1c864deb23a289a24224..88fe94a62a6d39d815458b68669f08a7f1c49529 100644 --- a/com.oracle.truffle.r.native/include/ed_Rinterface_gcntx +++ b/com.oracle.truffle.r.native/include/ed_Rinterface_gcntx @@ -12,6 +12,8 @@ extern SEXP R_getContextFun(CTXT); extern SEXP R_getContextCall(CTXT); extern SEXP R_getContextSrcRef(CTXT); extern int R_insideBrowser(); +extern int R_isGlobal(CTXT); +extern int R_isEqual(void*, void*); #else . +1 diff --git a/com.oracle.truffle.r.native/include/ed_Rinternals b/com.oracle.truffle.r.native/include/ed_Rinternals index 7aaafb1cd67144dfa7bfab280f75ba96bc8861f8..e4be8532d85dbe199c91ab944fd300e2f46ed299 100644 --- a/com.oracle.truffle.r.native/include/ed_Rinternals +++ b/com.oracle.truffle.r.native/include/ed_Rinternals @@ -64,4 +64,14 @@ LibExtern SEXP FASTR_NamespaceRegistry(); a #endif . +/R_PreserveObject/ +i +#ifdef FASTR +SEXP R_PreserveObject(SEXP); +#else +. ++1 +a +#endif +. w Rinternals.h diff --git a/com.oracle.truffle.r.native/library/lib.mk b/com.oracle.truffle.r.native/library/lib.mk index ea7cec010dbcade0f07cdea0399835266d1a1eae..727f096cb6a84cd50cc5e6250ce2aadc3e471375 100644 --- a/com.oracle.truffle.r.native/library/lib.mk +++ b/com.oracle.truffle.r.native/library/lib.mk @@ -109,7 +109,7 @@ $(LIB_PKG): $(C_OBJECTS) $(F_OBJECTS) $(GNUR_C_OBJECTS) $(GNUR_F_OBJECTS) $(PKGD mkdir -p $(FASTR_LIBRARY_DIR)/$(PKG)/libs cp $(LIB_PKG) $(FASTR_LIBRARY_DIR)/$(PKG)/libs ifeq ($(OS_NAME),Darwin) - install_name_tool -id $(FASTR_LIBRARY_DIR)/$(PKG)/libs/$(PKG).so $(FASTR_LIBRARY_DIR)/$(PKG)/libs/$(PKG).so + install_name_tool -id @rpath/../library/$(PKG)/libs/$(PKG).so $(FASTR_LIBRARY_DIR)/$(PKG)/libs/$(PKG).so endif $(OBJ)/%.o: $(SRC)/%.c $(H_SOURCES) diff --git a/com.oracle.truffle.r.native/library/tools/Makefile b/com.oracle.truffle.r.native/library/tools/Makefile index 5f351596d409a91ab6e83242d9a226dacd9d08eb..3bf843f9574ecd0e8361ef017dc4911a156257de 100644 --- a/com.oracle.truffle.r.native/library/tools/Makefile +++ b/com.oracle.truffle.r.native/library/tools/Makefile @@ -24,12 +24,27 @@ OBJ = lib GNUR_C_FILES = init.c +GRAMRD_C = gramRd.c +GRAMRD_OBJ := $(addprefix $(OBJ)/, gramRd.o) -GNUR_C_OBJECTS := $(addprefix $(OBJ)/, $(GNUR_C_FILES:.c=.o)) +GNUR_C_OBJECTS := $(addprefix $(OBJ)/, $(GNUR_C_FILES:.c=.o)) $(GRAMRD_OBJ) + +LIB_PKG_PRE = $(GRAMRD_OBJ) + +CLEAN_PKG = rm_gramRd include ../lib.mk +# in case already generated +C_OBJECTS := $(filter-out $(GRAMRD_OBJ), $(C_OBJECTS)) + $(C_OBJECTS): | $(OBJ) +$(SRC)/gramRd.c: $(GNUR_SRC)/gramRd.c + mx mkgramrd $(GNUR_SRC)/gramRd.c $(SRC)/gramRd.c + $(OBJ)/%.o: $(GNUR_SRC)/%.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.c b/com.oracle.truffle.r.native/library/tools/src/gramRd.c deleted file mode 100644 index bc835d36739c32f053bc6f1e9141cd8296745082..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.native/library/tools/src/gramRd.c +++ /dev/null @@ -1,4462 +0,0 @@ -// Slightly modified for use by FastR in a JNI environment - -/* A Bison parser, made by GNU Bison 2.7.12-4996. */ - -/* Bison implementation for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program 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 for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output. */ -#define YYBISON 1 - -/* Bison version. */ -#define YYBISON_VERSION "2.7.12-4996" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 0 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - - - - -/* Copy the first part of user declarations. */ - - -/* - * R : A Computer Langage for Statistical Data Analysis - * Copyright (C) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka - * Copyright (C) 1997--2015 The R Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * https://www.R-project.org/Licenses/ - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#define R_USE_SIGNALS 1 -//#include <Defn.h> -#include <Rinternals.h> -#include <R_ext/Parse.h> -#define STRICT_R_HEADERS -#include <R_ext/RS.h> /* for R_chk_* allocation */ -#include <ctype.h> -//#include <Rmath.h> /* for imax2(.),..*/ -#include <jni.h> - -#undef _ -#ifdef ENABLE_NLS -#include <libintl.h> -#define _(String) dgettext ("tools", String) -#else -#define _(String) (String) -#endif - -extern SEXP R_SrcrefSymbol; -extern SEXP R_SrcfileSymbol; -extern int R_ParseContextLast; -#define R_EOF -1 -#define PARSE_ERROR_SIZE 256 -#define PARSE_CONTEXT_SIZE 256 -static char R_ParseErrorMsg[PARSE_ERROR_SIZE]; -static char R_ParseContext[PARSE_CONTEXT_SIZE]; -int R_ParseContextLast; -int R_ParseContextLine; -int R_ParseError; -extern SEXP R_EmptyEnv; -extern SEXP R_NewHashedEnv(SEXP a, SEXP b); - -char *dgettext(const char *p, const char *msgid) { - return msgid; -} - -int imax2(int x, int y) -{ - return (x < y) ? y : x; -} - - -/* bison creates a non-static symbol yylloc in both gramLatex.o and gramRd.o, - so remap */ - -#define yylloc yyllocR - -#define DEBUGVALS 0 /* 1 causes detailed internal state output to R console */ -#define DEBUGMODE 0 /* 1 causes Bison output of parse state, to stdout or stderr */ - -static Rboolean wCalls = TRUE; -static Rboolean warnDups = FALSE; - -#define YYERROR_VERBOSE 1 - -static void yyerror(const char *); -static int yylex(); -static int yyparse(void); - -#define yyconst const - -typedef struct yyltype -{ - int first_line; - int first_column; - int first_byte; - - int last_line; - int last_column; - int last_byte; -} yyltype; - -# define YYLTYPE yyltype -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (N) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).first_byte = YYRHSLOC (Rhs, 1).first_byte; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - (Current).last_byte = YYRHSLOC (Rhs, N).last_byte; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - (Current).first_byte = (Current).last_byte = \ - YYRHSLOC (Rhs, 0).last_byte; \ - } \ - while (0) - -/* Useful defines so editors don't get confused ... */ - -#define LBRACE '{' -#define RBRACE '}' - -/* Functions used in the parsing process */ - -static SEXP GrowList(SEXP, SEXP); -static int KeywordLookup(const char *); -static SEXP UserMacroLookup(const char *); -static SEXP InstallKeywords(); -static SEXP NewList(void); -static SEXP makeSrcref(YYLTYPE *, SEXP); -static int xxgetc(); -static int xxungetc(int); - -/* Flags used to mark need for postprocessing in the dynamicFlag attribute */ - -#define STATIC 0 -#define HAS_IFDEF 1 -#define HAS_SEXPR 2 - -/* Internal lexer / parser state variables */ - -static char const yyunknown[] = "unknown macro"; /* our message, not bison's */ - - -typedef struct ParseState ParseState; -struct ParseState { - int xxinRString, xxQuoteLine, xxQuoteCol; - int xxinEqn; - int xxNewlineInString; - int xxlineno, xxbyteno, xxcolno; - int xxmode, xxitemType, xxbraceDepth; /* context for lexer */ - int xxDebugTokens; /* non-zero causes debug output to R console */ - const char* xxBasename; /* basename of file for error messages */ - SEXP Value; - int xxinitvalue; - SEXP xxMacroList;/* A hashed environment containing all the standard and user-defined macro names */ - ParseState *prevState; -}; - -static Rboolean busy = FALSE; -static ParseState parseState; - -#define RLIKE 1 /* Includes R strings; xxinRString holds the opening quote char, or 0 outside a string */ -#define LATEXLIKE 2 -#define VERBATIM 3 -#define INOPTION 4 -#define COMMENTMODE 5 /* only used in deparsing */ -#define UNKNOWNMODE 6 /* ditto */ - -static SEXP SrcFile; /* parse_Rd will *always* supply a srcfile */ - -/* Routines used to build the parse tree */ - -static SEXP xxpushMode(int, int, int); -static void xxpopMode(SEXP); -static SEXP xxnewlist(SEXP); -static SEXP xxnewlist2(SEXP, SEXP); -static SEXP xxnewlist3(SEXP, SEXP, SEXP); -static SEXP xxnewlist4(SEXP, SEXP, SEXP, SEXP); -static SEXP xxnewlist5(SEXP, SEXP, SEXP, SEXP, SEXP); -static SEXP xxnewlist6(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); -static SEXP xxnewlist7(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); -static SEXP xxnewlist8(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); -static SEXP xxnewlist9(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); - -static SEXP xxlist(SEXP, SEXP); -static SEXP xxmarkup(SEXP, SEXP, int, YYLTYPE *); -static SEXP xxmarkup2(SEXP, SEXP, SEXP, int, int, YYLTYPE *); -static SEXP xxmarkup3(SEXP, SEXP, SEXP, SEXP, int, YYLTYPE *); -static SEXP xxOptionmarkup(SEXP, SEXP, SEXP, int, YYLTYPE *); -static SEXP xxtag(SEXP, int, YYLTYPE *); -static void xxsavevalue(SEXP, YYLTYPE *); -static void xxWarnNewline(); -static SEXP xxnewcommand(SEXP, SEXP, SEXP, YYLTYPE *); -static SEXP xxusermacro(SEXP, SEXP, YYLTYPE *); -static int mkMarkup(int); -static int mkIfdef(int); -static int mkCode(int); -static int mkText(int); -static int mkVerb(int); -static int mkComment(int); - -#define YYSTYPE SEXP - - - - -# ifndef YY_NULL -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULL nullptr -# else -# define YY_NULL 0 -# endif -# endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif - - -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif -#if YYDEBUG -extern int yydebug; -#endif - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - END_OF_INPUT = 258, - ERROR = 259, - SECTIONHEADER = 260, - RSECTIONHEADER = 261, - VSECTIONHEADER = 262, - SECTIONHEADER2 = 263, - RCODEMACRO = 264, - SEXPR = 265, - RDOPTS = 266, - LATEXMACRO = 267, - VERBMACRO = 268, - OPTMACRO = 269, - ESCAPE = 270, - LISTSECTION = 271, - ITEMIZE = 272, - DESCRIPTION = 273, - NOITEM = 274, - LATEXMACRO2 = 275, - VERBMACRO2 = 276, - VERBLATEX = 277, - LATEXMACRO3 = 278, - NEWCOMMAND = 279, - USERMACRO = 280, - USERMACRO1 = 281, - USERMACRO2 = 282, - USERMACRO3 = 283, - USERMACRO4 = 284, - USERMACRO5 = 285, - USERMACRO6 = 286, - USERMACRO7 = 287, - USERMACRO8 = 288, - USERMACRO9 = 289, - IFDEF = 290, - ENDIF = 291, - TEXT = 292, - RCODE = 293, - VERB = 294, - COMMENT = 295, - UNKNOWN = 296, - STARTFILE = 297, - STARTFRAGMENT = 298 - }; -#endif -/* Tokens. */ -#define END_OF_INPUT 258 -#define ERROR 259 -#define SECTIONHEADER 260 -#define RSECTIONHEADER 261 -#define VSECTIONHEADER 262 -#define SECTIONHEADER2 263 -#define RCODEMACRO 264 -#define SEXPR 265 -#define RDOPTS 266 -#define LATEXMACRO 267 -#define VERBMACRO 268 -#define OPTMACRO 269 -#define ESCAPE 270 -#define LISTSECTION 271 -#define ITEMIZE 272 -#define DESCRIPTION 273 -#define NOITEM 274 -#define LATEXMACRO2 275 -#define VERBMACRO2 276 -#define VERBLATEX 277 -#define LATEXMACRO3 278 -#define NEWCOMMAND 279 -#define USERMACRO 280 -#define USERMACRO1 281 -#define USERMACRO2 282 -#define USERMACRO3 283 -#define USERMACRO4 284 -#define USERMACRO5 285 -#define USERMACRO6 286 -#define USERMACRO7 287 -#define USERMACRO8 288 -#define USERMACRO9 289 -#define IFDEF 290 -#define ENDIF 291 -#define TEXT 292 -#define RCODE 293 -#define VERB 294 -#define COMMENT 295 -#define UNKNOWN 296 -#define STARTFILE 297 -#define STARTFRAGMENT 298 - - - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef int YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -#endif - -#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED -typedef struct YYLTYPE -{ - int first_line; - int first_column; - int last_line; - int last_column; -} YYLTYPE; -# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ -# define YYLTYPE_IS_DECLARED 1 -# define YYLTYPE_IS_TRIVIAL 1 -#endif - -extern YYSTYPE yylval; -extern YYLTYPE yylloc; -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - - - -/* Copy the second part of user declarations. */ - - - -#ifdef short -# undef short -#endif - -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; -#endif - -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; -#elif (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -typedef signed char yytype_int8; -#else -typedef short int yytype_int8; -#endif - -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; -#else -typedef unsigned short int yytype_uint16; -#endif - -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; -#else -typedef short int yytype_int16; -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned int -# endif -#endif - -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) - -#ifndef YY_ -# if defined YYENABLE_NLS && YYENABLE_NLS -# if ENABLE_NLS -# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ -# define YY_(Msgid) dgettext ("bison-runtime", Msgid) -# endif -# endif -# ifndef YY_ -# define YY_(Msgid) Msgid -# endif -#endif - -#ifndef __attribute__ -/* This feature is available in gcc versions 2.5 and later. */ -# if (! defined __GNUC__ || __GNUC__ < 2 \ - || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)) -# define __attribute__(Spec) /* empty */ -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) -#else -# define YYUSE(E) /* empty */ -#endif - - -/* Identity function, used to suppress warnings about constant conditions. */ -#ifndef lint -# define YYID(N) (N) -#else -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static int -YYID (int yyi) -#else -static int -YYID (yyi) - int yyi; -#endif -{ - return yyi; -} -#endif - -#if ! defined yyoverflow || YYERROR_VERBOSE - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include <alloca.h> /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include <malloc.h> /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ - /* Use EXIT_SUCCESS as a witness for stdlib.h. */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined EXIT_SUCCESS \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ - - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ - && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yytype_int16 yyss_alloc; - YYSTYPE yyvs_alloc; - YYLTYPE yyls_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ - + 2 * YYSTACK_GAP_MAXIMUM) - -# define YYCOPY_NEEDED 1 - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (YYID (0)) - -#endif - -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from SRC to DST. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) -# else -# define YYCOPY(Dst, Src, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (Dst)[yyi] = (Src)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif -#endif /* !YYCOPY_NEEDED */ - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 33 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 832 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 48 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 31 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 89 -/* YYNRULES -- Number of states. */ -#define YYNSTATES 194 - -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ -#define YYUNDEFTOK 2 -#define YYMAXUTOK 298 - -#define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) - -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ -static const yytype_uint8 yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 46, 2, 47, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 44, 2, 45, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 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 -}; - -#if YYDEBUG -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in - YYRHS. */ -static const yytype_uint16 yyprhs[] = -{ - 0, 0, 3, 7, 11, 13, 16, 18, 20, 23, - 26, 29, 32, 35, 38, 42, 47, 52, 56, 61, - 63, 65, 67, 70, 72, 75, 77, 79, 81, 83, - 85, 87, 89, 91, 94, 97, 101, 106, 109, 112, - 116, 121, 124, 128, 133, 136, 139, 143, 145, 150, - 155, 159, 163, 165, 168, 172, 177, 183, 190, 198, - 208, 219, 231, 234, 237, 240, 243, 246, 249, 254, - 258, 261, 264, 269, 273, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 289, 292, 297, 301, 306 -}; - -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yytype_int8 yyrhs[] = -{ - 49, 0, -1, 42, 51, 3, -1, 43, 50, 3, - -1, 1, -1, 68, 54, -1, 52, -1, 53, -1, - 52, 53, -1, 7, 64, -1, 11, 64, -1, 6, - 62, -1, 5, 58, -1, 16, 61, -1, 8, 58, - 59, -1, 35, 67, 52, 36, -1, 35, 67, 52, - 1, -1, 10, 71, 63, -1, 10, 71, 78, 63, - -1, 40, -1, 37, -1, 57, -1, 1, 53, -1, - 55, -1, 54, 55, -1, 37, -1, 38, -1, 39, - -1, 40, -1, 41, -1, 77, -1, 56, -1, 57, - -1, 1, 55, -1, 12, 58, -1, 20, 58, 59, - -1, 23, 58, 59, 59, -1, 17, 60, -1, 18, - 61, -1, 14, 71, 58, -1, 14, 71, 78, 58, - -1, 9, 62, -1, 10, 71, 63, -1, 10, 71, - 78, 63, -1, 13, 64, -1, 21, 65, -1, 21, - 65, 66, -1, 15, -1, 35, 67, 54, 36, -1, - 35, 67, 54, 1, -1, 22, 64, 59, -1, 24, - 65, 64, -1, 25, -1, 26, 64, -1, 27, 64, - 64, -1, 28, 64, 64, 64, -1, 29, 64, 64, - 64, 64, -1, 30, 64, 64, 64, 64, 64, -1, - 31, 64, 64, 64, 64, 64, 64, -1, 32, 64, - 64, 64, 64, 64, 64, 64, 64, -1, 33, 64, - 64, 64, 64, 64, 64, 64, 64, 64, -1, 34, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - -1, 68, 77, -1, 68, 77, -1, 68, 37, -1, - 75, 77, -1, 76, 77, -1, 69, 77, -1, 44, - 70, 54, 45, -1, 44, 70, 45, -1, 72, 77, - -1, 73, 77, -1, 44, 74, 54, 45, -1, 44, - 74, 45, -1, 68, 37, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 44, 54, 45, -1, 44, - 45, -1, 44, 54, 1, 45, -1, 44, 1, 45, - -1, 44, 54, 1, 3, -1, 46, 55, 47, -1 -}; - -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const yytype_uint16 yyrline[] = -{ - 0, 214, 214, 215, 216, 219, 222, 225, 226, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 243, 244, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 274, 275, 276, 277, 279, 281, 283, 285, 287, - 290, 293, 298, 300, 301, 310, 312, 314, 318, 319, - 321, 323, 327, 328, 330, 333, 335, 337, 339, 341, - 343, 345, 347, 349, 351, 352, 353, 354, 355, 357 -}; -#endif - -#if YYDEBUG || YYERROR_VERBOSE || 0 -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "$end", "error", "$undefined", "END_OF_INPUT", "ERROR", "SECTIONHEADER", - "RSECTIONHEADER", "VSECTIONHEADER", "SECTIONHEADER2", "RCODEMACRO", - "SEXPR", "RDOPTS", "LATEXMACRO", "VERBMACRO", "OPTMACRO", "ESCAPE", - "LISTSECTION", "ITEMIZE", "DESCRIPTION", "NOITEM", "LATEXMACRO2", - "VERBMACRO2", "VERBLATEX", "LATEXMACRO3", "NEWCOMMAND", "USERMACRO", - "USERMACRO1", "USERMACRO2", "USERMACRO3", "USERMACRO4", "USERMACRO5", - "USERMACRO6", "USERMACRO7", "USERMACRO8", "USERMACRO9", "IFDEF", "ENDIF", - "TEXT", "RCODE", "VERB", "COMMENT", "UNKNOWN", "STARTFILE", - "STARTFRAGMENT", "'{'", "'}'", "'['", "']'", "$accept", "Init", - "RdFragment", "RdFile", "SectionList", "Section", "ArgItems", "Item", - "Markup", "UserMacro", "LatexArg", "LatexArg2", "Item0Arg", "Item2Arg", - "RLikeArg", "RLikeArg2", "VerbatimArg", "VerbatimArg1", "VerbatimArg2", - "IfDefTarget", "goLatexLike", "goRLike", "goRLike2", "goOption", - "goVerbatim", "goVerbatim1", "goVerbatim2", "goItem0", "goItem2", "Arg", - "Option", YY_NULL -}; -#endif - -# ifdef YYPRINT -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to - token YYLEX-NUM. */ -static const yytype_uint16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 123, 125, 91, 93 -}; -# endif - -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint8 yyr1[] = -{ - 0, 48, 49, 49, 49, 50, 51, 52, 52, 53, - 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, - 53, 53, 53, 54, 54, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 58, 59, 59, 60, 61, 62, 63, 63, - 64, 65, 66, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, 77, 77, 77, 77, 78 -}; - -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = -{ - 0, 2, 3, 3, 1, 2, 1, 1, 2, 2, - 2, 2, 2, 2, 3, 4, 4, 3, 4, 1, - 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 2, 3, 4, 2, 2, 3, - 4, 2, 3, 4, 2, 2, 3, 1, 4, 4, - 3, 3, 1, 2, 3, 4, 5, 6, 7, 9, - 10, 11, 2, 2, 2, 2, 2, 2, 4, 3, - 2, 2, 4, 3, 2, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 2, 4, 3, 4, 3 -}; - -/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE doesn't specify something else to do. Zero - means the default is an error. */ -static const yytype_uint8 yydefact[] = -{ - 0, 4, 0, 75, 0, 0, 75, 76, 79, 75, - 78, 79, 83, 80, 52, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 75, 20, 19, 0, 0, 7, - 21, 0, 0, 1, 22, 12, 0, 11, 0, 9, - 0, 75, 0, 10, 13, 0, 79, 0, 53, 79, - 79, 79, 79, 79, 79, 79, 79, 0, 0, 2, - 8, 3, 0, 76, 78, 75, 79, 78, 47, 82, - 83, 75, 80, 79, 75, 75, 25, 26, 27, 28, - 29, 0, 0, 23, 31, 32, 30, 62, 67, 70, - 14, 0, 77, 0, 17, 0, 66, 51, 71, 54, - 79, 79, 79, 79, 79, 79, 79, 0, 74, 33, - 41, 0, 34, 44, 75, 37, 0, 38, 75, 45, - 75, 75, 0, 0, 85, 0, 24, 64, 63, 0, - 0, 18, 55, 79, 79, 79, 79, 79, 79, 0, - 15, 42, 0, 39, 75, 65, 35, 81, 46, 50, - 75, 0, 87, 0, 84, 69, 0, 89, 56, 79, - 79, 79, 79, 79, 43, 40, 0, 36, 0, 48, - 88, 86, 68, 57, 79, 79, 79, 79, 73, 0, - 58, 79, 79, 79, 72, 79, 79, 79, 59, 79, - 79, 60, 79, 61 -}; - -/* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = -{ - -1, 4, 31, 27, 28, 29, 82, 83, 84, 85, - 35, 90, 115, 44, 37, 94, 39, 46, 148, 57, - 36, 38, 129, 42, 40, 47, 166, 116, 45, 86, - 95 -}; - -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -#define YYPACT_NINF -94 -static const yytype_int16 yypact[] = -{ - 28, -94, 792, -94, 20, 792, -94, -94, -94, -94, - -94, -94, -94, -94, -94, -94, -94, -94, -94, -94, - -94, -94, -94, -94, -94, -94, -94, 29, 718, -94, - -94, 34, 638, -94, -94, -94, -19, -94, -19, -94, - -19, -94, -30, -94, -94, -19, -94, -19, -94, -94, - -94, -94, -94, -94, -94, -94, -94, 792, -6, -94, - -94, -94, 638, -94, -94, -94, -94, -94, -94, -94, - -94, -94, -94, -94, -94, -94, -94, -94, -94, -94, - -94, 265, 556, -94, -94, -94, -94, -94, -94, -94, - -94, -22, -94, 638, -94, 2, -94, -94, -94, -94, - -94, -94, -94, -94, -94, -94, -94, 755, -94, -94, - -94, -30, -94, -94, 1, -94, -19, -94, -94, 4, - -94, -94, 638, 306, -94, 347, -94, -94, -94, 388, - 7, -94, -94, -94, -94, -94, -94, -94, -94, 680, - -94, -94, 2, -94, -94, -94, -94, -94, -94, -94, - -94, 597, -94, 224, -94, -94, 429, -94, -94, -94, - -94, -94, -94, -94, -94, -94, 470, -94, 179, -94, - -94, -94, -94, -94, -94, -94, -94, -94, -94, 511, - -94, -94, -94, -94, -94, -94, -94, -94, -94, -94, - -94, -94, -94, -94 -}; - -/* YYPGOTO[NTERM-NUM]. */ -static const yytype_int8 yypgoto[] = -{ - -94, -94, -94, -94, 3, -2, -64, -10, -94, 22, - -8, -43, -94, -9, -4, -93, -11, -5, -94, -7, - 10, -94, -94, -31, -94, -94, -94, -94, -94, -17, - -58 -}; - -/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -50 -static const yytype_int16 yytable[] = -{ - 43, 41, 131, 34, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 32, 92, 127, 93, 125, 141, 87, - 33, 88, 81, 89, 30, 81, 60, 30, 96, 1, - 98, 108, 59, 111, 58, 97, 114, 61, 99, 100, - 101, 102, 103, 104, 105, 106, 92, 93, 147, 164, - 30, 91, 109, 142, 157, 113, 144, 112, 151, 110, - 107, 117, 120, 118, 0, 156, 121, 119, 122, 0, - 2, 3, 126, 0, 128, 146, 0, 149, 150, 30, - 0, 0, 0, 130, 0, 58, 0, 0, 0, 132, - 133, 134, 135, 136, 137, 138, 0, 0, 0, 145, - 0, 0, 179, 0, 0, 60, 143, 167, 0, 0, - 0, 0, 0, 109, 0, 126, 0, 0, 0, 0, - 0, 0, 158, 159, 160, 161, 162, 163, 91, 30, - 91, 91, 0, 0, 0, 0, 165, 34, 0, 0, - 0, 126, 0, 109, 0, 0, 126, 0, 173, 174, - 175, 176, 177, 0, 0, 0, 0, 0, 109, 0, - 91, 30, 0, 180, 181, 182, 183, 0, 0, 126, - 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, - 62, 193, -49, 0, 0, 0, 0, 0, 63, 64, - 0, 65, 66, 67, 68, 0, 69, 70, 0, 71, - 72, 73, 74, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 75, -49, 76, 77, 78, 79, - 80, 0, 0, 81, -49, 62, -49, 170, 0, 0, - 0, 0, 0, 63, 64, 0, 65, 66, 67, 68, - 0, 69, 70, 0, 71, 72, 73, 74, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 75, - 0, 76, 77, 78, 79, 80, 123, 0, 81, 171, - 0, 0, 0, 0, 63, 64, 0, 65, 66, 67, - 68, 0, 69, 70, 0, 71, 72, 73, 74, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 75, 0, 76, 77, 78, 79, 80, 62, 0, 81, - 124, 0, 0, 0, 0, 63, 64, 0, 65, 66, - 67, 68, 0, 69, 70, 0, 71, 72, 73, 74, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 23, 75, 0, 76, 77, 78, 79, 80, 153, 0, - 81, 152, 0, 0, 0, 0, 63, 64, 0, 65, - 66, 67, 68, 0, 69, 70, 0, 71, 72, 73, - 74, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 75, 0, 76, 77, 78, 79, 80, 62, - 0, 81, 154, 0, 0, 0, 0, 63, 64, 0, - 65, 66, 67, 68, 0, 69, 70, 0, 71, 72, - 73, 74, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 75, 0, 76, 77, 78, 79, 80, - 62, 0, 81, 155, 0, 0, 0, 0, 63, 64, - 0, 65, 66, 67, 68, 0, 69, 70, 0, 71, - 72, 73, 74, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 75, 0, 76, 77, 78, 79, - 80, 62, 0, 81, 172, 0, 0, 0, 0, 63, - 64, 0, 65, 66, 67, 68, 0, 69, 70, 0, - 71, 72, 73, 74, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 75, 0, 76, 77, 78, - 79, 80, 62, 0, 81, 178, 0, 0, 0, 0, - 63, 64, 0, 65, 66, 67, 68, 0, 69, 70, - 0, 71, 72, 73, 74, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 75, 0, 76, 77, - 78, 79, 80, 0, 0, 81, 184, 62, 0, -5, - 0, 0, 0, 0, 0, 63, 64, 0, 65, 66, - 67, 68, 0, 69, 70, 0, 71, 72, 73, 74, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 23, 75, 0, 76, 77, 78, 79, 80, 168, 0, - 81, 0, 0, 0, 0, 0, 63, 64, 0, 65, - 66, 67, 68, 0, 69, 70, 0, 71, 72, 73, - 74, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 75, 169, 76, 77, 78, 79, 80, 62, - 0, 81, 0, 0, 0, 0, 0, 63, 64, 0, - 65, 66, 67, 68, 0, 69, 70, 0, 71, 72, - 73, 74, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 75, 0, 76, 77, 78, 79, 80, - 0, 5, 81, -16, 0, 6, 7, 8, 9, 0, - 10, 11, 0, 0, 0, 0, 12, 0, 0, 0, - 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, -16, 25, 0, 5, - 26, -6, 0, 6, 7, 8, 9, 0, 10, 11, - 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, - 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 0, 25, 139, 0, 26, 0, - 6, 7, 8, 9, 0, 10, 11, 0, 0, 0, - 0, 12, 0, 0, 0, 0, 0, 0, 0, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 140, 25, 5, 0, 26, 0, 6, 7, 8, - 9, 0, 10, 11, 0, 0, 0, 0, 12, 0, - 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 0, 25, - 0, 0, 26 -}; - -#define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-94))) - -#define yytable_value_is_error(Yytable_value) \ - YYID (0) - -static const yytype_int16 yycheck[] = -{ - 11, 9, 95, 5, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 3, 44, 37, 46, 81, 111, 36, - 0, 38, 44, 40, 2, 44, 28, 5, 45, 1, - 47, 37, 3, 64, 24, 46, 67, 3, 49, 50, - 51, 52, 53, 54, 55, 56, 44, 46, 44, 142, - 28, 41, 62, 111, 47, 66, 114, 65, 122, 63, - 57, 70, 73, 71, -1, 129, 74, 72, 75, -1, - 42, 43, 82, -1, 91, 118, -1, 120, 121, 57, - -1, -1, -1, 93, -1, 75, -1, -1, -1, 100, - 101, 102, 103, 104, 105, 106, -1, -1, -1, 116, - -1, -1, 166, -1, -1, 107, 114, 150, -1, -1, - -1, -1, -1, 123, -1, 125, -1, -1, -1, -1, - -1, -1, 133, 134, 135, 136, 137, 138, 118, 107, - 120, 121, -1, -1, -1, -1, 144, 139, -1, -1, - -1, 151, -1, 153, -1, -1, 156, -1, 159, 160, - 161, 162, 163, -1, -1, -1, -1, -1, 168, -1, - 150, 139, -1, 174, 175, 176, 177, -1, -1, 179, - 181, 182, 183, -1, 185, 186, 187, -1, 189, 190, - 1, 192, 3, -1, -1, -1, -1, -1, 9, 10, - -1, 12, 13, 14, 15, -1, 17, 18, -1, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, -1, -1, 44, 45, 1, 47, 3, -1, -1, - -1, -1, -1, 9, 10, -1, 12, 13, 14, 15, - -1, 17, 18, -1, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - -1, 37, 38, 39, 40, 41, 1, -1, 44, 45, - -1, -1, -1, -1, 9, 10, -1, 12, 13, 14, - 15, -1, 17, 18, -1, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, -1, 37, 38, 39, 40, 41, 1, -1, 44, - 45, -1, -1, -1, -1, 9, 10, -1, 12, 13, - 14, 15, -1, 17, 18, -1, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, -1, 37, 38, 39, 40, 41, 1, -1, - 44, 45, -1, -1, -1, -1, 9, 10, -1, 12, - 13, 14, 15, -1, 17, 18, -1, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, -1, 37, 38, 39, 40, 41, 1, - -1, 44, 45, -1, -1, -1, -1, 9, 10, -1, - 12, 13, 14, 15, -1, 17, 18, -1, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, -1, 37, 38, 39, 40, 41, - 1, -1, 44, 45, -1, -1, -1, -1, 9, 10, - -1, 12, 13, 14, 15, -1, 17, 18, -1, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, -1, 37, 38, 39, 40, - 41, 1, -1, 44, 45, -1, -1, -1, -1, 9, - 10, -1, 12, 13, 14, 15, -1, 17, 18, -1, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, -1, 37, 38, 39, - 40, 41, 1, -1, 44, 45, -1, -1, -1, -1, - 9, 10, -1, 12, 13, 14, 15, -1, 17, 18, - -1, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, -1, 37, 38, - 39, 40, 41, -1, -1, 44, 45, 1, -1, 3, - -1, -1, -1, -1, -1, 9, 10, -1, 12, 13, - 14, 15, -1, 17, 18, -1, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, -1, 37, 38, 39, 40, 41, 1, -1, - 44, -1, -1, -1, -1, -1, 9, 10, -1, 12, - 13, 14, 15, -1, 17, 18, -1, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 1, - -1, 44, -1, -1, -1, -1, -1, 9, 10, -1, - 12, 13, 14, 15, -1, 17, 18, -1, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, -1, 37, 38, 39, 40, 41, - -1, 1, 44, 3, -1, 5, 6, 7, 8, -1, - 10, 11, -1, -1, -1, -1, 16, -1, -1, -1, - -1, -1, -1, -1, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, -1, 1, - 40, 3, -1, 5, 6, 7, 8, -1, 10, 11, - -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, - -1, -1, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, -1, 37, 1, -1, 40, -1, - 5, 6, 7, 8, -1, 10, 11, -1, -1, -1, - -1, 16, -1, -1, -1, -1, -1, -1, -1, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 1, -1, 40, -1, 5, 6, 7, - 8, -1, 10, 11, -1, -1, -1, -1, 16, -1, - -1, -1, -1, -1, -1, -1, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, -1, 37, - -1, -1, 40 -}; - -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_uint8 yystos[] = -{ - 0, 1, 42, 43, 49, 1, 5, 6, 7, 8, - 10, 11, 16, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 37, 40, 51, 52, 53, - 57, 50, 68, 0, 53, 58, 68, 62, 69, 64, - 72, 58, 71, 64, 61, 76, 65, 73, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 67, 68, 3, - 53, 3, 1, 9, 10, 12, 13, 14, 15, 17, - 18, 20, 21, 22, 23, 35, 37, 38, 39, 40, - 41, 44, 54, 55, 56, 57, 77, 77, 77, 77, - 59, 68, 44, 46, 63, 78, 77, 64, 77, 64, - 64, 64, 64, 64, 64, 64, 64, 52, 37, 55, - 62, 71, 58, 64, 71, 60, 75, 61, 58, 65, - 64, 58, 67, 1, 45, 54, 55, 37, 77, 70, - 55, 63, 64, 64, 64, 64, 64, 64, 64, 1, - 36, 63, 78, 58, 78, 77, 59, 44, 66, 59, - 59, 54, 45, 1, 45, 45, 54, 47, 64, 64, - 64, 64, 64, 64, 63, 58, 74, 59, 1, 36, - 3, 45, 45, 64, 64, 64, 64, 64, 45, 54, - 64, 64, 64, 64, 45, 64, 64, 64, 64, 64, - 64, 64, 64, 64 -}; - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab - - -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. However, - YYFAIL appears to be in use. Nevertheless, it is formally deprecated - in Bison 2.4.2's NEWS entry, where a plan to phase it out is - discussed. */ - -#define YYFAIL goto yyerrlab -#if defined YYFAIL - /* This is here to suppress warnings from the GCC cpp's - -Wunused-macros. Normally we don't worry about that warning, but - some users do, and we want to make it easy for users to remove - YYFAIL uses, which will produce warnings from Bison 2.5. */ -#endif - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (YYID (0)) - -/* Error token number */ -#define YYTERROR 1 -#define YYERRCODE 256 - - -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) - - -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - -#ifndef YY_LOCATION_PRINT -# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL - -/* Print *YYLOCP on YYO. Private, do not rely on its existence. */ - -__attribute__((__unused__)) -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static unsigned -yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) -#else -static unsigned -yy_location_print_ (yyo, yylocp) - FILE *yyo; - YYLTYPE const * const yylocp; -#endif -{ - unsigned res = 0; - int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; - if (0 <= yylocp->first_line) - { - res += fprintf (yyo, "%d", yylocp->first_line); - if (0 <= yylocp->first_column) - res += fprintf (yyo, ".%d", yylocp->first_column); - } - if (0 <= yylocp->last_line) - { - if (yylocp->first_line < yylocp->last_line) - { - res += fprintf (yyo, "-%d", yylocp->last_line); - if (0 <= end_col) - res += fprintf (yyo, ".%d", end_col); - } - else if (0 <= end_col && yylocp->first_column < end_col) - res += fprintf (yyo, "-%d", end_col); - } - return res; - } - -# define YY_LOCATION_PRINT(File, Loc) \ - yy_location_print_ (File, &(Loc)) - -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif -#endif - - -/* YYLEX -- calling `yylex' with the right arguments. */ -#ifdef YYLEX_PARAM -# define YYLEX yylex (YYLEX_PARAM) -#else -# define YYLEX yylex () -#endif - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (YYID (0)) - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value, Location); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (YYID (0)) - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp) -#else -static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; - YYLTYPE const * const yylocationp; -#endif -{ - FILE *yyo = yyoutput; - YYUSE (yyo); - if (!yyvaluep) - return; - YYUSE (yylocationp); -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# else - YYUSE (yyoutput); -# endif - YYUSE (yytype); -} - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp) -#else -static void -yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; - YYLTYPE const * const yylocationp; -#endif -{ - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - - YY_LOCATION_PRINT (yyoutput, *yylocationp); - YYFPRINTF (yyoutput, ": "); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp); - YYFPRINTF (yyoutput, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) -#else -static void -yy_stack_print (yybottom, yytop) - yytype_int16 *yybottom; - yytype_int16 *yytop; -#endif -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (YYID (0)) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule) -#else -static void -yy_reduce_print (yyvsp, yylsp, yyrule) - YYSTYPE *yyvsp; - YYLTYPE *yylsp; - int yyrule; -#endif -{ - int yynrhs = yyr2[yyrule]; - int yyi; - unsigned long int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], - &(yyvsp[(yyi + 1) - (yynrhs)]) - , &(yylsp[(yyi + 1) - (yynrhs)]) ); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyvsp, yylsp, Rule); \ -} while (YYID (0)) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - -#if YYERROR_VERBOSE - -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static YYSIZE_T -yystrlen (const char *yystr) -#else -static YYSIZE_T -yystrlen (yystr) - const char *yystr; -#endif -{ - YYSIZE_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -# endif - -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static char * -yystpcpy (char *yydest, const char *yysrc) -#else -static char * -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -#endif -{ - char *yyd = yydest; - const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif - -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - YYSIZE_T yyn = 0; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (! yyres) - return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; -} -# endif - -/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN for the state stack whose top is - YYSSP. - - Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is - not large enough to hold the message. In that case, also set - *YYMSG_ALLOC to the required number of bytes. Return 2 if the - required number of bytes is too large to store. */ -static int -yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, - yytype_int16 *yyssp, int yytoken) -{ - YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); - YYSIZE_T yysize = yysize0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - /* Internationalized format string. */ - const char *yyformat = YY_NULL; - /* Arguments of yyformat. */ - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - /* Number of reported tokens (one for the "unexpected", one per - "expected"). */ - int yycount = 0; - - /* There are many possibilities here to consider: - - Assume YYFAIL is not used. It's too flawed to consider. See - <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html> - for details. YYERROR is fine as it does not invoke this - function. - - If this state is a consistent state with a default action, then - the only way this function was invoked is if the default action - is an error action. In that case, don't check for expected - tokens because there are none. - - The only way there can be no lookahead present (in yychar) is if - this state is a consistent state with a default action. Thus, - detecting the absence of a lookahead is sufficient to determine - that there is no unexpected or expected token to report. In that - case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this state is a - consistent state with a default action. There might have been a - previous inconsistent state, consistent state with a non-default - action, or user semantic action that manipulated yychar. - - Of course, the expected token list depends on states to have - correct lookahead information, and it depends on the parser not - to perform extra reductions after fetching a lookahead from the - scanner and before detecting a syntax error. Thus, state merging - (from LALR or IELR) and default reductions corrupt the expected - token list. However, the list is correct for canonical LR with - one exception: it will still contain any token that will not be - accepted due to an error action in a later state. - */ - if (yytoken != YYEMPTY) - { - int yyn = yypact[*yyssp]; - yyarg[yycount++] = yytname[yytoken]; - if (!yypact_value_is_default (yyn)) - { - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. In other words, skip the first -YYN actions for - this state because they are default actions. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yyx; - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR - && !yytable_value_is_error (yytable[yyx + yyn])) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - break; - } - yyarg[yycount++] = yytname[yyx]; - { - YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - } - } - } - - switch (yycount) - { -# define YYCASE_(N, S) \ - case N: \ - yyformat = S; \ - break - YYCASE_(0, YY_("syntax error")); - YYCASE_(1, YY_("syntax error, unexpected %s")); - YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); - YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); - YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); - YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -# undef YYCASE_ - } - - { - YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - - if (*yymsg_alloc < yysize) - { - *yymsg_alloc = 2 * yysize; - if (! (yysize <= *yymsg_alloc - && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) - *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return 1; - } - - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - { - char *yyp = *yymsg; - int yyi = 0; - while ((*yyp = *yyformat) != '\0') - if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyformat += 2; - } - else - { - yyp++; - yyformat++; - } - } - return 0; -} -#endif /* YYERROR_VERBOSE */ - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp) -#else -static void -yydestruct (yymsg, yytype, yyvaluep, yylocationp) - const char *yymsg; - int yytype; - YYSTYPE *yyvaluep; - YYLTYPE *yylocationp; -#endif -{ - YYUSE (yyvaluep); - YYUSE (yylocationp); - - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - - switch (yytype) - { - case 5: /* SECTIONHEADER */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 6: /* RSECTIONHEADER */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 7: /* VSECTIONHEADER */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 8: /* SECTIONHEADER2 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 9: /* RCODEMACRO */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 10: /* SEXPR */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 12: /* LATEXMACRO */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 13: /* VERBMACRO */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 14: /* OPTMACRO */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 15: /* ESCAPE */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 16: /* LISTSECTION */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 17: /* ITEMIZE */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 18: /* DESCRIPTION */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 19: /* NOITEM */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 20: /* LATEXMACRO2 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 21: /* VERBMACRO2 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 22: /* VERBLATEX */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 23: /* LATEXMACRO3 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 24: /* NEWCOMMAND */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 25: /* USERMACRO */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 26: /* USERMACRO1 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 27: /* USERMACRO2 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 28: /* USERMACRO3 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 29: /* USERMACRO4 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 30: /* USERMACRO5 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 31: /* USERMACRO6 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 32: /* USERMACRO7 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 33: /* USERMACRO8 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 34: /* USERMACRO9 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 35: /* IFDEF */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 36: /* ENDIF */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 37: /* TEXT */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 38: /* RCODE */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 39: /* VERB */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 40: /* COMMENT */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 41: /* UNKNOWN */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 42: /* STARTFILE */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 43: /* STARTFRAGMENT */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 54: /* ArgItems */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 58: /* LatexArg */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 63: /* RLikeArg2 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 65: /* VerbatimArg1 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 66: /* VerbatimArg2 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 67: /* IfDefTarget */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 68: /* goLatexLike */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 69: /* goRLike */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 70: /* goRLike2 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 71: /* goOption */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 72: /* goVerbatim */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 73: /* goVerbatim1 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 74: /* goVerbatim2 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 75: /* goItem0 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 76: /* goItem2 */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - case 78: /* Option */ - - { UNPROTECT_PTR((*yyvaluep)); }; - - break; - - default: - break; - } -} - - - - -/* The lookahead symbol. */ -int yychar; - - -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END -#endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif - -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval YY_INITIAL_VALUE(yyval_default); - -/* Location data for the lookahead symbol. */ -YYLTYPE yylloc -# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL - = { 1, 1, 1, 1 } -# endif -; - - -/* Number of syntax errors so far. */ -int yynerrs; - - -/*----------. -| yyparse. | -`----------*/ - -#ifdef YYPARSE_PARAM -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void *YYPARSE_PARAM) -#else -int -yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -#endif -#else /* ! YYPARSE_PARAM */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void) -#else -int -yyparse () - -#endif -#endif -{ - int yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - `yyss': related to states. - `yyvs': related to semantic values. - `yyls': related to locations. - - Refer to the stacks through separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - /* The location stack. */ - YYLTYPE yylsa[YYINITDEPTH]; - YYLTYPE *yyls; - YYLTYPE *yylsp; - - /* The locations where the error started and ended. */ - YYLTYPE yyerror_range[3]; - - YYSIZE_T yystacksize; - - int yyn; - int yyresult; - /* Lookahead token as an internal (translated) token number. */ - int yytoken = 0; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - YYLTYPE yyloc; - -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa; - yylsp = yyls = yylsa; - yystacksize = YYINITDEPTH; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - yylsp[0] = yylloc; - goto yysetstate; - -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - yysetstate: - *yyssp = yystate; - - if (yyss + yystacksize - 1 <= yyssp) - { - /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; - -#ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - YYLTYPE *yyls1 = yyls; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yyls1, yysize * sizeof (*yylsp), - &yystacksize); - - yyls = yyls1; - yyss = yyss1; - yyvs = yyvs1; - } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); - YYSTACK_RELOCATE (yyls_alloc, yyls); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif -#endif /* no yyoverflow */ - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - yylsp = yyls + yysize - 1; - - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } - - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yypact_value_is_default (yyn)) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; - } - - if (yychar <= YYEOF) - { - yychar = yytoken = YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yytable_value_is_error (yyn)) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token. */ - yychar = YYEMPTY; - - yystate = yyn; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - *++yylsp = yylloc; - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - /* Default location. */ - YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 2: - - { xxsavevalue((yyvsp[(2) - (3)]), &(yyloc)); UNPROTECT_PTR((yyvsp[(1) - (3)])); YYACCEPT; } - break; - - case 3: - - { xxsavevalue((yyvsp[(2) - (3)]), &(yyloc)); UNPROTECT_PTR((yyvsp[(1) - (3)])); YYACCEPT; } - break; - - case 4: - - { PROTECT(parseState.Value = R_NilValue); YYABORT; } - break; - - case 5: - - { (yyval) = (yyvsp[(2) - (2)]); UNPROTECT_PTR((yyvsp[(1) - (2)])); } - break; - - case 6: - - { (yyval) = (yyvsp[(1) - (1)]); } - break; - - case 7: - - { (yyval) = xxnewlist((yyvsp[(1) - (1)])); } - break; - - case 8: - - { (yyval) = xxlist((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)])); } - break; - - case 9: - - { (yyval) = xxmarkup((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]), STATIC, &(yyloc)); } - break; - - case 10: - - { (yyval) = xxmarkup((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]), HAS_SEXPR, &(yyloc)); } - break; - - case 11: - - { (yyval) = xxmarkup((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]), STATIC, &(yyloc)); } - break; - - case 12: - - { (yyval) = xxmarkup((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]), STATIC, &(yyloc)); } - break; - - case 13: - - { (yyval) = xxmarkup((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]), STATIC, &(yyloc)); } - break; - - case 14: - - { (yyval) = xxmarkup2((yyvsp[(1) - (3)]), (yyvsp[(2) - (3)]), (yyvsp[(3) - (3)]), 2, STATIC, &(yyloc)); } - break; - - case 15: - - { (yyval) = xxmarkup2((yyvsp[(1) - (4)]), (yyvsp[(2) - (4)]), (yyvsp[(3) - (4)]), 2, HAS_IFDEF, &(yyloc)); UNPROTECT_PTR((yyvsp[(4) - (4)])); } - break; - - case 16: - - { (yyval) = xxmarkup2((yyvsp[(1) - (4)]), (yyvsp[(2) - (4)]), (yyvsp[(3) - (4)]), 2, HAS_IFDEF, &(yyloc)); } - break; - - case 17: - - { (yyval) = xxmarkup((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), HAS_SEXPR, &(yyloc)); xxpopMode((yyvsp[(2) - (3)])); } - break; - - case 18: - - { (yyval) = xxOptionmarkup((yyvsp[(1) - (4)]), (yyvsp[(3) - (4)]), (yyvsp[(4) - (4)]), HAS_SEXPR, &(yyloc)); xxpopMode((yyvsp[(2) - (4)])); } - break; - - case 19: - - { (yyval) = xxtag((yyvsp[(1) - (1)]), COMMENT, &(yyloc)); } - break; - - case 20: - - { (yyval) = xxtag((yyvsp[(1) - (1)]), TEXT, &(yyloc)); } - break; - - case 21: - - { (yyval) = (yyvsp[(1) - (1)]); } - break; - - case 22: - - { (yyval) = (yyvsp[(2) - (2)]); } - break; - - case 23: - - { (yyval) = xxnewlist((yyvsp[(1) - (1)])); } - break; - - case 24: - - { (yyval) = xxlist((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)])); } - break; - - case 25: - - { (yyval) = xxtag((yyvsp[(1) - (1)]), TEXT, &(yyloc)); } - break; - - case 26: - - { (yyval) = xxtag((yyvsp[(1) - (1)]), RCODE, &(yyloc)); } - break; - - case 27: - - { (yyval) = xxtag((yyvsp[(1) - (1)]), VERB, &(yyloc)); } - break; - - case 28: - - { (yyval) = xxtag((yyvsp[(1) - (1)]), COMMENT, &(yyloc)); } - break; - - case 29: - - { (yyval) = xxtag((yyvsp[(1) - (1)]), UNKNOWN, &(yyloc)); yyerror(yyunknown); } - break; - - case 30: - - { (yyval) = xxmarkup(R_NilValue, (yyvsp[(1) - (1)]), STATIC, &(yyloc)); } - break; - - case 31: - - { (yyval) = (yyvsp[(1) - (1)]); } - break; - - case 32: - - { (yyval) = (yyvsp[(1) - (1)]); } - break; - - case 33: - - { (yyval) = (yyvsp[(2) - (2)]); } - break; - - case 34: - - { (yyval) = xxmarkup((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]), STATIC, &(yyloc)); } - break; - - case 35: - - { (yyval) = xxmarkup2((yyvsp[(1) - (3)]), (yyvsp[(2) - (3)]), (yyvsp[(3) - (3)]), 2, STATIC, &(yyloc)); } - break; - - case 36: - - { (yyval) = xxmarkup3((yyvsp[(1) - (4)]), (yyvsp[(2) - (4)]), (yyvsp[(3) - (4)]), (yyvsp[(4) - (4)]), STATIC, &(yyloc)); } - break; - - case 37: - - { (yyval) = xxmarkup((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]), STATIC, &(yyloc)); } - break; - - case 38: - - { (yyval) = xxmarkup((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]), STATIC, &(yyloc)); } - break; - - case 39: - - { (yyval) = xxmarkup((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), STATIC, &(yyloc)); xxpopMode((yyvsp[(2) - (3)])); } - break; - - case 40: - - { (yyval) = xxOptionmarkup((yyvsp[(1) - (4)]), (yyvsp[(3) - (4)]), (yyvsp[(4) - (4)]), STATIC, &(yyloc)); xxpopMode((yyvsp[(2) - (4)])); } - break; - - case 41: - - { (yyval) = xxmarkup((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]), STATIC, &(yyloc)); } - break; - - case 42: - - { (yyval) = xxmarkup((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), HAS_SEXPR, &(yyloc)); xxpopMode((yyvsp[(2) - (3)])); } - break; - - case 43: - - { (yyval) = xxOptionmarkup((yyvsp[(1) - (4)]), (yyvsp[(3) - (4)]), (yyvsp[(4) - (4)]), HAS_SEXPR, &(yyloc)); xxpopMode((yyvsp[(2) - (4)])); } - break; - - case 44: - - { (yyval) = xxmarkup((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]), STATIC, &(yyloc)); } - break; - - case 45: - - { (yyval) = xxmarkup2((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]), R_NilValue, 1, STATIC, &(yyloc)); } - break; - - case 46: - - { (yyval) = xxmarkup2((yyvsp[(1) - (3)]), (yyvsp[(2) - (3)]), (yyvsp[(3) - (3)]), 2, STATIC, &(yyloc)); } - break; - - case 47: - - { (yyval) = xxmarkup((yyvsp[(1) - (1)]), R_NilValue, STATIC, &(yyloc)); } - break; - - case 48: - - { (yyval) = xxmarkup2((yyvsp[(1) - (4)]), (yyvsp[(2) - (4)]), (yyvsp[(3) - (4)]), 2, HAS_IFDEF, &(yyloc)); UNPROTECT_PTR((yyvsp[(4) - (4)])); } - break; - - case 49: - - { (yyval) = xxmarkup2((yyvsp[(1) - (4)]), (yyvsp[(2) - (4)]), (yyvsp[(3) - (4)]), 2, HAS_IFDEF, &(yyloc)); } - break; - - case 50: - - { (yyval) = xxmarkup2((yyvsp[(1) - (3)]), (yyvsp[(2) - (3)]), (yyvsp[(3) - (3)]), 2, STATIC, &(yyloc)); } - break; - - case 51: - - { (yyval) = xxnewcommand((yyvsp[(1) - (3)]), (yyvsp[(2) - (3)]), (yyvsp[(3) - (3)]), &(yyloc)); } - break; - - case 52: - - { (yyval) = xxusermacro((yyvsp[(1) - (1)]), xxnewlist(NULL), &(yyloc)); } - break; - - case 53: - - { (yyval) = xxusermacro((yyvsp[(1) - (2)]), xxnewlist((yyvsp[(2) - (2)])), &(yyloc)); } - break; - - case 54: - - { (yyval) = xxusermacro((yyvsp[(1) - (3)]), xxnewlist2((yyvsp[(2) - (3)]), (yyvsp[(3) - (3)])), &(yyloc)); } - break; - - case 55: - - { (yyval) = xxusermacro((yyvsp[(1) - (4)]), xxnewlist3((yyvsp[(2) - (4)]), (yyvsp[(3) - (4)]), (yyvsp[(4) - (4)])), &(yyloc)); } - break; - - case 56: - - { (yyval) = xxusermacro((yyvsp[(1) - (5)]), xxnewlist4((yyvsp[(2) - (5)]), (yyvsp[(3) - (5)]), (yyvsp[(4) - (5)]), (yyvsp[(5) - (5)])), &(yyloc)); } - break; - - case 57: - - { (yyval) = xxusermacro((yyvsp[(1) - (6)]), xxnewlist5((yyvsp[(2) - (6)]), (yyvsp[(3) - (6)]), (yyvsp[(4) - (6)]), (yyvsp[(5) - (6)]), (yyvsp[(6) - (6)])), &(yyloc)); } - break; - - case 58: - - { (yyval) = xxusermacro((yyvsp[(1) - (7)]), xxnewlist6((yyvsp[(2) - (7)]), (yyvsp[(3) - (7)]), (yyvsp[(4) - (7)]), (yyvsp[(5) - (7)]), (yyvsp[(6) - (7)]), (yyvsp[(7) - (7)])), &(yyloc)); } - break; - - case 59: - - { (yyval) = xxusermacro((yyvsp[(1) - (9)]), xxnewlist7((yyvsp[(2) - (9)]), (yyvsp[(3) - (9)]), (yyvsp[(4) - (9)]), (yyvsp[(5) - (9)]), (yyvsp[(6) - (9)]), (yyvsp[(7) - (9)]), (yyvsp[(8) - (9)])), &(yyloc)); } - break; - - case 60: - - { (yyval) = xxusermacro((yyvsp[(1) - (10)]), xxnewlist8((yyvsp[(2) - (10)]), (yyvsp[(3) - (10)]), (yyvsp[(4) - (10)]), (yyvsp[(5) - (10)]), (yyvsp[(6) - (10)]), (yyvsp[(7) - (10)]), (yyvsp[(8) - (10)]), (yyvsp[(9) - (10)])), &(yyloc)); } - break; - - case 61: - - { (yyval) = xxusermacro((yyvsp[(1) - (11)]), xxnewlist9((yyvsp[(2) - (11)]), (yyvsp[(3) - (11)]), (yyvsp[(4) - (11)]), (yyvsp[(5) - (11)]), (yyvsp[(6) - (11)]), (yyvsp[(7) - (11)]), (yyvsp[(8) - (11)]), (yyvsp[(9) - (11)]), (yyvsp[(10) - (11)])), &(yyloc)); } - break; - - case 62: - - { xxpopMode((yyvsp[(1) - (2)])); (yyval) = (yyvsp[(2) - (2)]); } - break; - - case 63: - - { xxpopMode((yyvsp[(1) - (2)])); (yyval) = (yyvsp[(2) - (2)]); } - break; - - case 64: - - { xxpopMode((yyvsp[(1) - (2)])); (yyval) = xxnewlist((yyvsp[(2) - (2)])); - if(wCalls) - warning(_("bad markup (extra space?) at %s:%d:%d"), - parseState.xxBasename, (yylsp[(2) - (2)]).first_line, (yylsp[(2) - (2)]).first_column); - else - warningcall(R_NilValue, _("bad markup (extra space?) at %s:%d:%d"), - parseState.xxBasename, (yylsp[(2) - (2)]).first_line, (yylsp[(2) - (2)]).first_column); - } - break; - - case 65: - - { xxpopMode((yyvsp[(1) - (2)])); (yyval) = (yyvsp[(2) - (2)]); } - break; - - case 66: - - { xxpopMode((yyvsp[(1) - (2)])); (yyval) = (yyvsp[(2) - (2)]); } - break; - - case 67: - - { xxpopMode((yyvsp[(1) - (2)])); (yyval) = (yyvsp[(2) - (2)]); } - break; - - case 68: - - { xxpopMode((yyvsp[(2) - (4)])); (yyval) = (yyvsp[(3) - (4)]); } - break; - - case 69: - - { xxpopMode((yyvsp[(2) - (3)])); (yyval) = xxnewlist(NULL); } - break; - - case 70: - - { xxpopMode((yyvsp[(1) - (2)])); (yyval) = (yyvsp[(2) - (2)]); } - break; - - case 71: - - { xxpopMode((yyvsp[(1) - (2)])); (yyval) = (yyvsp[(2) - (2)]); } - break; - - case 72: - - { xxpopMode((yyvsp[(2) - (4)])); (yyval) = (yyvsp[(3) - (4)]); } - break; - - case 73: - - { xxpopMode((yyvsp[(2) - (3)])); (yyval) = xxnewlist(NULL); } - break; - - case 74: - - { xxpopMode((yyvsp[(1) - (2)])); (yyval) = xxnewlist(xxtag((yyvsp[(2) - (2)]), TEXT, &(yyloc))); } - break; - - case 75: - - { (yyval) = xxpushMode(LATEXLIKE, UNKNOWN, FALSE); } - break; - - case 76: - - { (yyval) = xxpushMode(RLIKE, UNKNOWN, FALSE); } - break; - - case 77: - - { parseState.xxbraceDepth--; (yyval) = xxpushMode(RLIKE, UNKNOWN, FALSE); parseState.xxbraceDepth++; } - break; - - case 78: - - { (yyval) = xxpushMode(INOPTION, UNKNOWN, FALSE); } - break; - - case 79: - - { (yyval) = xxpushMode(VERBATIM, UNKNOWN, FALSE); } - break; - - case 80: - - { (yyval) = xxpushMode(VERBATIM, UNKNOWN, TRUE); } - break; - - case 81: - - { parseState.xxbraceDepth--; (yyval) = xxpushMode(VERBATIM, UNKNOWN, FALSE); parseState.xxbraceDepth++; } - break; - - case 82: - - { (yyval) = xxpushMode(LATEXLIKE, ESCAPE, FALSE); } - break; - - case 83: - - { (yyval) = xxpushMode(LATEXLIKE, LATEXMACRO2, FALSE); } - break; - - case 84: - - { (yyval) = (yyvsp[(2) - (3)]); } - break; - - case 85: - - { (yyval) = xxnewlist(NULL); } - break; - - case 86: - - { (yyval) = (yyvsp[(2) - (4)]); } - break; - - case 87: - - { (yyval) = xxnewlist(NULL); } - break; - - case 88: - - { (yyval) = (yyvsp[(2) - (4)]); } - break; - - case 89: - - { (yyval) = (yyvsp[(2) - (3)]); } - break; - - - - default: break; - } - /* User semantic actions sometimes alter yychar, and that requires - that yytoken be updated with the new translation. We take the - approach of translating immediately before every use of yytoken. - One alternative is translating here after every semantic action, - but that translation would be missed if the semantic action invokes - YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or - if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an - incorrect destructor might then be invoked immediately. In the - case of YYERROR or YYBACKUP, subsequent parser actions might lead - to an incorrect destructor call or verbose syntax error message - before the lookahead is translated. */ - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - - *++yyvsp = yyval; - *++yylsp = yyloc; - - /* Now `shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; - - goto yynewstate; - - -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ -yyerrlab: - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); - - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; -#if ! YYERROR_VERBOSE - yyerror (YY_("syntax error")); -#else -# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ - yyssp, yytoken) - { - char const *yymsgp = YY_("syntax error"); - int yysyntax_error_status; - yysyntax_error_status = YYSYNTAX_ERROR; - if (yysyntax_error_status == 0) - yymsgp = yymsg; - else if (yysyntax_error_status == 1) - { - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); - if (!yymsg) - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - yysyntax_error_status = 2; - } - else - { - yysyntax_error_status = YYSYNTAX_ERROR; - yymsgp = yymsg; - } - } - yyerror (yymsgp); - if (yysyntax_error_status == 2) - goto yyexhaustedlab; - } -# undef YYSYNTAX_ERROR -#endif - } - - yyerror_range[1] = yylloc; - - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval, &yylloc); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - yyerror_range[1] = yylsp[1-yylen]; - /* Do not reclaim the symbols of the rule which action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - for (;;) - { - yyn = yypact[yystate]; - if (!yypact_value_is_default (yyn)) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - yyerror_range[1] = *yylsp; - yydestruct ("Error: popping", - yystos[yystate], yyvsp, yylsp); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - yyerror_range[2] = yylloc; - /* Using YYLLOC is tempting, but would change the location of - the lookahead. YYLOC is available though. */ - YYLLOC_DEFAULT (yyloc, yyerror_range, 2); - *++yylsp = yyloc; - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - -#if !defined yyoverflow || YYERROR_VERBOSE -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (YY_("memory exhausted")); - yyresult = 2; - /* Fall through. */ -#endif - -yyreturn: - if (yychar != YYEMPTY) - { - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, &yylloc); - } - /* Do not reclaim the symbols of the rule which action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp, yylsp); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif -#if YYERROR_VERBOSE - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); -#endif - /* Make sure YYID is used. */ - return YYID (yyresult); -} - - - - - -static SEXP xxpushMode(int newmode, int newitem, int neweqn) -{ - SEXP ans; - PROTECT(ans = allocVector(INTSXP, 7)); - - INTEGER(ans)[0] = parseState.xxmode; /* Lexer mode */ - INTEGER(ans)[1] = parseState.xxitemType; /* What is \item? */ - INTEGER(ans)[2] = parseState.xxbraceDepth; /* Brace depth used in RCODE and VERBATIM */ - INTEGER(ans)[3] = parseState.xxinRString; /* Quote char that started a string */ - INTEGER(ans)[4] = parseState.xxQuoteLine; /* Where the quote was */ - INTEGER(ans)[5] = parseState.xxQuoteCol; /* " */ - INTEGER(ans)[6] = parseState.xxinEqn; /* In the first arg to \eqn or \deqn: no escapes */ - -#if DEBUGMODE - Rprintf("xxpushMode(%d, %s) pushes %d, %s, %d\n", newmode, yytname[YYTRANSLATE(newitem)], - parseState.xxmode, yytname[YYTRANSLATE(parseState.xxitemType)], parseState.xxbraceDepth); -#endif - parseState.xxmode = newmode; - parseState.xxitemType = newitem; - parseState.xxbraceDepth = 0; - parseState.xxinRString = 0; - parseState.xxinEqn = neweqn; - - return ans; -} - -static void xxpopMode(SEXP oldmode) -{ -#if DEBUGVALS - Rprintf("xxpopMode(%d, %s, %d) replaces %d, %s, %d\n", INTEGER(oldmode)[0], yytname[YYTRANSLATE(INTEGER(oldmode)[1])], INTEGER(oldmode)[2], - parseState.xxmode, yytname[YYTRANSLATE(parseState.xxitemType)], parseState.xxbraceDepth); -#endif - parseState.xxmode = INTEGER(oldmode)[0]; - parseState.xxitemType = INTEGER(oldmode)[1]; - parseState.xxbraceDepth = INTEGER(oldmode)[2]; - parseState.xxinRString = INTEGER(oldmode)[3]; - parseState.xxQuoteLine = INTEGER(oldmode)[4]; - parseState.xxQuoteCol = INTEGER(oldmode)[5]; - parseState.xxinEqn = INTEGER(oldmode)[6]; - - UNPROTECT_PTR(oldmode); -} - -static int getDynamicFlag(SEXP item) -{ - SEXP flag = getAttrib(item, install("dynamicFlag")); - if (isNull(flag)) return 0; - else return INTEGER(flag)[0]; -} - -static void setDynamicFlag(SEXP item, int flag) -{ - if (flag) { - SEXP s_dynamicFlag = install("dynamicFlag"); - setAttrib(item, s_dynamicFlag, ScalarInteger(flag)); - } -} - -static SEXP xxnewlist(SEXP item) -{ - SEXP ans, tmp; -#if DEBUGVALS - Rprintf("xxnewlist(item=%p)", item); -#endif - PROTECT(tmp = NewList()); - if (item) { - int flag = getDynamicFlag(item); - PROTECT(ans = GrowList(tmp, item)); - setDynamicFlag(ans, flag); - UNPROTECT_PTR(tmp); - UNPROTECT_PTR(item); - } else ans = tmp; -#if DEBUGVALS - Rprintf(" result: %p is length %d\n", ans, length(ans)); -#endif - return ans; -} - -static SEXP xxnewlist2(SEXP item1, SEXP item2) -{ - return xxlist(xxnewlist(item1), item2); -} - -static SEXP xxnewlist3(SEXP item1, SEXP item2, SEXP item3) -{ - return xxlist(xxnewlist2(item1, item2), item3); -} - -static SEXP xxnewlist4(SEXP item1, SEXP item2, SEXP item3, SEXP item4) -{ - return xxlist(xxnewlist3(item1, item2, item3), item4); -} - -static SEXP xxnewlist5(SEXP item1, SEXP item2, SEXP item3, SEXP item4, SEXP item5) -{ - return xxlist(xxnewlist4(item1, item2, item3, item4), item5); -} - -static SEXP xxnewlist6(SEXP item1, SEXP item2, SEXP item3, SEXP item4, SEXP item5, - SEXP item6) -{ - return xxlist(xxnewlist5(item1, item2, item3, item4, item5), item6); -} - -static SEXP xxnewlist7(SEXP item1, SEXP item2, SEXP item3, SEXP item4, SEXP item5, - SEXP item6, SEXP item7) -{ - return xxlist(xxnewlist6(item1, item2, item3, item4, item5, item6), item7); -} - -static SEXP xxnewlist8(SEXP item1, SEXP item2, SEXP item3, SEXP item4, SEXP item5, - SEXP item6, SEXP item7, SEXP item8) -{ - return xxlist(xxnewlist7(item1, item2, item3, item4, item5, item6, item7), item8); -} - -static SEXP xxnewlist9(SEXP item1, SEXP item2, SEXP item3, SEXP item4, SEXP item5, - SEXP item6, SEXP item7, SEXP item8, SEXP item9) -{ - return xxlist(xxnewlist8(item1, item2, item3, item4, item5, item6, item7, item8), - item9); -} - -static SEXP xxlist(SEXP oldlist, SEXP item) -{ - SEXP ans; - int flag = getDynamicFlag(oldlist) | getDynamicFlag(item); -#if DEBUGVALS - Rprintf("xxlist(oldlist=%p, item=%p)", oldlist, item); -#endif - PROTECT(ans = GrowList(oldlist, item)); - UNPROTECT_PTR(item); - UNPROTECT_PTR(oldlist); - setDynamicFlag(ans, flag); -#if DEBUGVALS - Rprintf(" result: %p is length %d\n", ans, length(ans)); -#endif - return ans; -} - -static SEXP xxmarkup(SEXP header, SEXP body, int flag, YYLTYPE *lloc) -{ - SEXP ans; -#if DEBUGVALS - Rprintf("xxmarkup(header=%p, body=%p)", header, body); -#endif - if (isNull(body)) - PROTECT(ans = allocVector(VECSXP, 0)); - else { - flag |= getDynamicFlag(body); - PROTECT(ans = PairToVectorList(CDR(body))); - UNPROTECT_PTR(body); - } - if (isNull(header)) - PROTECT(header = mkString("LIST")); - - setAttrib(ans, install("Rd_tag"), header); - setAttrib(ans, R_SrcrefSymbol, makeSrcref(lloc, SrcFile)); - UNPROTECT_PTR(header); - setDynamicFlag(ans, flag); -#if DEBUGVALS - Rprintf(" result: %p\n", ans); -#endif - return ans; -} - -static SEXP xxnewcommand(SEXP cmd, SEXP name, SEXP defn, YYLTYPE *lloc) -{ - SEXP ans, prev, thename, thedefn; - char buffer[128]; - const char *c; - int maxarg = 0; -#if DEBUGVALS - Rprintf("xxnewcommand(cmd=%p, name=%p, defn=%p)", cmd, name, defn); -#endif - thename = CADR(name); - thedefn = CADR(defn); - if (TYPEOF(thedefn) == STRSXP) - PROTECT(thedefn = mkString(CHAR(STRING_ELT(thedefn,0)))); - else - PROTECT(thedefn = mkString("")); - if (warnDups) { - prev = findVar(installChar(STRING_ELT(thename, 0)), parseState.xxMacroList); - if (prev != R_UnboundValue && strcmp(CHAR(STRING_ELT(cmd,0)), "\\renewcommand")) { - snprintf(buffer, sizeof(buffer), _("Macro '%s' previously defined."), - CHAR(STRING_ELT(thename, 0))); - yyerror(buffer); - } - } - for (c = CHAR(STRING_ELT(thedefn, 0)); *c; c++) { - if (*c == '#' && isdigit(*(c+1))) - maxarg = imax2(maxarg, *(c+1) - '0'); - } - if (maxarg > 4) { - snprintf(buffer, sizeof(buffer), _("At most 4 arguments are allowed for user defined macros.")); - yyerror(buffer); - } - PROTECT(ans = ScalarInteger(USERMACRO + maxarg)); - setAttrib(ans, install("Rd_tag"), cmd); - setAttrib(ans, install("definition"), thedefn); - setAttrib(ans, R_SrcrefSymbol, makeSrcref(lloc, SrcFile)); - defineVar(installChar(STRING_ELT(thename, 0)), ans, parseState.xxMacroList); - - UNPROTECT_PTR(thedefn); - UNPROTECT_PTR(cmd); - UNPROTECT_PTR(name); - UNPROTECT_PTR(defn); - return ans; -} - -#define START_MACRO -2 -#define END_MACRO -3 - -static SEXP xxusermacro(SEXP macro, SEXP args, YYLTYPE *lloc) -{ - SEXP ans, value, nextarg; - int i,len; - const char *c, *start ; - -#if DEBUGVALS - Rprintf("xxusermacro(macro=%p, args=%p)", macro, args); -#endif - len = length(args)-1; - PROTECT(ans = allocVector(STRSXP, len + 1)); - value = UserMacroLookup(CHAR(STRING_ELT(macro,0))); - if (TYPEOF(value) == STRSXP) - SET_STRING_ELT(ans, 0, STRING_ELT(value, 0)); - else - error(_("No macro definition for '%s'."), CHAR(STRING_ELT(macro,0))); -/* Rprintf("len = %d", len); */ - for (i = 0, nextarg=args; i < len; i++, nextarg = CDR(nextarg)) { -/* Rprintf("arg i is"); - PrintValue(CADR(CADR(nextarg))); */ - SET_STRING_ELT(ans, i+1, STRING_ELT(CADR(CADR(nextarg)), 0)); - } - UNPROTECT_PTR(args); - UNPROTECT_PTR(macro); - /* Now push the expanded macro onto the input stream, in reverse order */ - xxungetc(END_MACRO); - start = CHAR(STRING_ELT(ans, 0)); - for (c = start + strlen(start); c > start; c--) { - if (c > start + 1 && *(c-2) == '#' && isdigit(*(c-1))) { - int which = *(c-1) - '0'; - const char *arg = CHAR(STRING_ELT(ans, which)); - for (size_t ii = strlen(arg); ii > 0; ii--) xxungetc(arg[ii-1]); - c--; - } else { - xxungetc(*(c-1)); - } - } - xxungetc(START_MACRO); - - SEXP s_Rd_tag = install("Rd_tag"); - setAttrib(ans, s_Rd_tag, mkString("USERMACRO")); - setAttrib(ans, R_SrcrefSymbol, makeSrcref(lloc, SrcFile)); -#if DEBUGVALS - Rprintf(" result: %p\n", ans); -#endif - return ans; -} - -static SEXP xxOptionmarkup(SEXP header, SEXP option, SEXP body, int flag, YYLTYPE *lloc) -{ - SEXP ans; -#if DEBUGVALS - Rprintf("xxOptionmarkup(header=%p, option=%p, body=%p)", header, option, body); -#endif - flag |= getDynamicFlag(body); - PROTECT(ans = PairToVectorList(CDR(body))); - UNPROTECT_PTR(body); - setAttrib(ans, install("Rd_tag"), header); - UNPROTECT_PTR(header); - flag |= getDynamicFlag(option); - setAttrib(ans, install("Rd_option"), option); - UNPROTECT_PTR(option); - setAttrib(ans, R_SrcrefSymbol, makeSrcref(lloc, SrcFile)); - setDynamicFlag(ans, flag); -#if DEBUGVALS - Rprintf(" result: %p\n", ans); -#endif - return ans; -} - -static SEXP xxmarkup2(SEXP header, SEXP body1, SEXP body2, int argcount, int flag, YYLTYPE *lloc) -{ - SEXP ans; -#if DEBUGVALS - Rprintf("xxmarkup2(header=%p, body1=%p, body2=%p)", header, body1, body2); -#endif - - PROTECT(ans = allocVector(VECSXP, argcount)); - if (!isNull(body1)) { - int flag1 = getDynamicFlag(body1); - SET_VECTOR_ELT(ans, 0, PairToVectorList(CDR(body1))); - UNPROTECT_PTR(body1); - setDynamicFlag(VECTOR_ELT(ans, 0), flag1); - flag |= flag1; - } - if (!isNull(body2)) { - int flag2; - if (argcount < 2) error("internal error: inconsistent argument count"); - flag2 = getDynamicFlag(body2); - SET_VECTOR_ELT(ans, 1, PairToVectorList(CDR(body2))); - UNPROTECT_PTR(body2); - setDynamicFlag(VECTOR_ELT(ans, 1), flag2); - flag |= flag2; - } - setAttrib(ans, install("Rd_tag"), header); - UNPROTECT_PTR(header); - setAttrib(ans, R_SrcrefSymbol, makeSrcref(lloc, SrcFile)); - setDynamicFlag(ans, flag); -#if DEBUGVALS - Rprintf(" result: %p\n", ans); -#endif - return ans; -} - -static SEXP xxmarkup3(SEXP header, SEXP body1, SEXP body2, SEXP body3, int flag, YYLTYPE *lloc) -{ - SEXP ans; -#if DEBUGVALS - Rprintf("xxmarkup2(header=%p, body1=%p, body2=%p, body3=%p)", header, body1, body2, body3); -#endif - - PROTECT(ans = allocVector(VECSXP, 3)); - if (!isNull(body1)) { - int flag1 = getDynamicFlag(body1); - SET_VECTOR_ELT(ans, 0, PairToVectorList(CDR(body1))); - UNPROTECT_PTR(body1); - setDynamicFlag(VECTOR_ELT(ans, 0), flag1); - flag |= flag1; - } - if (!isNull(body2)) { - int flag2; - flag2 = getDynamicFlag(body2); - SET_VECTOR_ELT(ans, 1, PairToVectorList(CDR(body2))); - UNPROTECT_PTR(body2); - setDynamicFlag(VECTOR_ELT(ans, 1), flag2); - flag |= flag2; - } - if (!isNull(body3)) { - int flag3; - flag3 = getDynamicFlag(body3); - SET_VECTOR_ELT(ans, 2, PairToVectorList(CDR(body3))); - UNPROTECT_PTR(body3); - setDynamicFlag(VECTOR_ELT(ans, 2), flag3); - flag |= flag3; - } - setAttrib(ans, install("Rd_tag"), header); - UNPROTECT_PTR(header); - setAttrib(ans, R_SrcrefSymbol, makeSrcref(lloc, SrcFile)); - setDynamicFlag(ans, flag); -#if DEBUGVALS - Rprintf(" result: %p\n", ans); -#endif - return ans; -} - -static void xxsavevalue(SEXP Rd, YYLTYPE *lloc) -{ - int flag = getDynamicFlag(Rd); - PROTECT(parseState.Value = PairToVectorList(CDR(Rd))); - if (!isNull(parseState.Value)) { - setAttrib(parseState.Value, R_ClassSymbol, mkString("Rd")); - setAttrib(parseState.Value, R_SrcrefSymbol, makeSrcref(lloc, SrcFile)); - setDynamicFlag(parseState.Value, flag); - } - UNPROTECT_PTR(Rd); -} - -static SEXP xxtag(SEXP item, int type, YYLTYPE *lloc) -{ - SEXP s_Rd_tag = install("Rd_tag"); - setAttrib(item, s_Rd_tag, mkString(yytname[YYTRANSLATE(type)])); - setAttrib(item, R_SrcrefSymbol, makeSrcref(lloc, SrcFile)); - return item; -} - -static void xxWarnNewline() -{ - if (parseState.xxNewlineInString) { - if(wCalls) - warning(_("newline within quoted string at %s:%d"), - parseState.xxBasename, parseState.xxNewlineInString); - else - warningcall(R_NilValue, - _("newline within quoted string at %s:%d"), - parseState.xxBasename, parseState.xxNewlineInString); - } -} - - -/*----------------------------------------------------------------------------*/ - - -static int (*ptr_getc)(void); - -/* Private pushback, since file ungetc only guarantees one byte. - We need arbitrarily large size, since this is how macros are expanded. */ - -#define PUSH_BACK(c) do { \ - if (npush >= pushsize - 1) { \ - int *old = pushbase; \ - pushsize *= 2; \ - pushbase = malloc(pushsize*sizeof(int)); \ - if(!pushbase) error(_("unable to allocate buffer for long macro at line %d"), parseState.xxlineno);\ - memmove(pushbase, old, npush*sizeof(int)); \ - if(old != pushback) free(old); } \ - pushbase[npush++] = (c); \ -} while(0) - - - -#define PUSHBACK_BUFSIZE 32 - -static int pushback[PUSHBACK_BUFSIZE]; -static int *pushbase; -static unsigned int npush, pushsize; -static int macrolevel; -static int prevpos = 0; -static int prevlines[PUSHBACK_BUFSIZE]; -static int prevcols[PUSHBACK_BUFSIZE]; -static int prevbytes[PUSHBACK_BUFSIZE]; - - -static int xxgetc(void) -{ - int c, oldpos; - - do { - if(npush) { - c = pushbase[--npush]; - if (c == START_MACRO) { - macrolevel++; - if (macrolevel > 1000) - error(_("macros nested too deeply: infinite recursion?")); - } else if (c == END_MACRO) macrolevel--; - } else c = ptr_getc(); - } while (c == START_MACRO || c == END_MACRO); - - if (!macrolevel) { - oldpos = prevpos; - prevpos = (prevpos + 1) % PUSHBACK_BUFSIZE; - prevbytes[prevpos] = parseState.xxbyteno; - prevlines[prevpos] = parseState.xxlineno; - /* We only advance the column for the 1st byte in UTF-8, so handle later bytes specially */ - if (0x80 <= (unsigned char)c && (unsigned char)c <= 0xBF) { - parseState.xxcolno--; - prevcols[prevpos] = prevcols[oldpos]; - } else - prevcols[prevpos] = parseState.xxcolno; - - if (c == EOF) return R_EOF; - - R_ParseContextLast = (R_ParseContextLast + 1) % PARSE_CONTEXT_SIZE; - R_ParseContext[R_ParseContextLast] = (char) c; - - if (c == '\n') { - parseState.xxlineno += 1; - parseState.xxcolno = 1; - parseState.xxbyteno = 1; - } else { - parseState.xxcolno++; - parseState.xxbyteno++; - } - - if (c == '\t') parseState.xxcolno = ((parseState.xxcolno + 6) & ~7) + 1; - - R_ParseContextLine = parseState.xxlineno; - } - /* Rprintf("get %c\n", c); */ - return c; -} - -static int xxungetc(int c) -{ - /* this assumes that c was the result of xxgetc; if not, some edits will be needed */ - if (c == END_MACRO) macrolevel++; - if (!macrolevel) { - parseState.xxlineno = prevlines[prevpos]; - parseState.xxbyteno = prevbytes[prevpos]; - parseState.xxcolno = prevcols[prevpos]; - prevpos = (prevpos + PUSHBACK_BUFSIZE - 1) % PUSHBACK_BUFSIZE; - - R_ParseContextLine = parseState.xxlineno; - - R_ParseContext[R_ParseContextLast] = '\0'; - /* Mac OS X requires us to keep this non-negative */ - R_ParseContextLast = (R_ParseContextLast + PARSE_CONTEXT_SIZE - 1) - % PARSE_CONTEXT_SIZE; - } - if (c == START_MACRO) macrolevel--; - PUSH_BACK(c); - /* Rprintf("unget %c;", c); */ - return c; -} - -static SEXP makeSrcref(YYLTYPE *lloc, SEXP srcfile) -{ - SEXP val; - - PROTECT(val = allocVector(INTSXP, 6)); - INTEGER(val)[0] = lloc->first_line; - INTEGER(val)[1] = lloc->first_byte; - INTEGER(val)[2] = lloc->last_line; - INTEGER(val)[3] = lloc->last_byte; - INTEGER(val)[4] = lloc->first_column; - INTEGER(val)[5] = lloc->last_column; - setAttrib(val, R_SrcfileSymbol, srcfile); - setAttrib(val, R_ClassSymbol, mkString("srcref")); - UNPROTECT(1); - return val; -} - -static SEXP mkString2(const char *s, size_t len) -{ - SEXP t; - cetype_t enc = CE_UTF8; - - PROTECT(t = allocVector(STRSXP, 1)); - SET_STRING_ELT(t, 0, mkCharLenCE(s, (int) len, enc)); - UNPROTECT(1); - return t; -} - - -/* Stretchy List Structures : Lists are created and grown using a special */ -/* dotted pair. The CAR of the list points to the last cons-cell in the */ -/* list and the CDR points to the first. The list can be extracted from */ -/* the pair by taking its CDR, while the CAR gives fast access to the end */ -/* of the list. */ - - -/* Create a stretchy-list dotted pair */ - -static SEXP NewList(void) -{ - SEXP s = CONS(R_NilValue, R_NilValue); - SETCAR(s, s); - return s; -} - -/* Add a new element at the end of a stretchy list */ - -static SEXP GrowList(SEXP l, SEXP s) -{ - SEXP tmp; - PROTECT(s); - tmp = CONS(s, R_NilValue); - UNPROTECT(1); - SETCDR(CAR(l), tmp); - SETCAR(l, tmp); - return l; -} - -/*--------------------------------------------------------------------------*/ - -static SEXP ParseRd(ParseStatus *status, SEXP srcfile, Rboolean fragment, SEXP macros) -{ - Rboolean keepmacros = !isLogical(macros) || asLogical(macros); - - R_ParseContextLast = 0; - R_ParseContext[0] = '\0'; - - parseState.xxlineno = 1; - parseState.xxcolno = 1; - parseState.xxbyteno = 1; - - SrcFile = srcfile; - - npush = 0; - pushbase = pushback; - pushsize = PUSHBACK_BUFSIZE; - macrolevel = 0; - - parseState.xxmode = LATEXLIKE; - parseState.xxitemType = UNKNOWN; - parseState.xxbraceDepth = 0; - parseState.xxinRString = 0; - parseState.xxNewlineInString = 0; - parseState.xxinEqn = 0; - if (fragment) parseState.xxinitvalue = STARTFRAGMENT; - else parseState.xxinitvalue = STARTFILE; - - if (!isEnvironment(macros)) - macros = InstallKeywords(); - - PROTECT(macros); - PROTECT(parseState.xxMacroList = R_NewHashedEnv(macros, ScalarInteger(0))); - UNPROTECT_PTR(macros); - - parseState.Value = R_NilValue; - - if (yyparse()) *status = PARSE_ERROR; - else *status = PARSE_OK; - - if (keepmacros && !isNull(parseState.Value)) - setAttrib(parseState.Value, install("macros"), parseState.xxMacroList); - -#if DEBUGVALS - Rprintf("ParseRd result: %p\n", parseState.Value); -#endif - UNPROTECT_PTR(parseState.Value); - UNPROTECT_PTR(parseState.xxMacroList); - - if (pushbase != pushback) free(pushbase); - - return parseState.Value; -} - -//#include "Rconnections.h" -typedef SEXP Rconnection; -static int Rconn_fgetc(Rconnection con) { - return -1; -} - -extern JNIEnv *getEnv(); - -static Rconnection con_parse; -static jmethodID getcMethodID; - -/* need to handle incomplete last line */ -static int con_getc(void) -{ - int c; - static int last=-1000; - JNIEnv *env = getEnv(); - c = (*env)->CallIntMethod(env, con_parse, getcMethodID, con_parse); - if (c == EOF && last != '\n') c = '\n'; - return (last = c); -} - -static -SEXP R_ParseRd(Rconnection con, ParseStatus *status, SEXP srcfile, Rboolean fragment, SEXP macros) -{ - con_parse = con; - JNIEnv *env = getEnv(); - jclass klass = (*env)->FindClass(env, "com/oracle/truffle/r/runtime/conn/RConnection"); - getcMethodID = (*env)->GetMethodID(env, klass, "getc", "()I"); - ptr_getc = con_getc; - return ParseRd(status, srcfile, fragment, macros); -} - -/*---------------------------------------------------------------------------- - * - * The Lexical Analyzer: - * - * Basic lexical analysis is performed by the following - * routines. - * - * The function yylex() scans the input, breaking it into - * tokens which are then passed to the parser. - * - */ - - -/* Special Symbols */ -/* Section and R code headers */ - -struct { - char *name; - int token; -} - -/* When adding keywords here, make sure all the handlers - are also modified: checkRd, Rd2HTML, Rd2latex, Rd2txt, any other new ones... */ - -static keywords[] = { - /* These sections contain Latex-like text */ - - { "\\author", SECTIONHEADER }, - { "\\concept", SECTIONHEADER }, - { "\\description",SECTIONHEADER }, - { "\\details", SECTIONHEADER }, - { "\\docType", SECTIONHEADER }, - - { "\\encoding",SECTIONHEADER }, - { "\\format", SECTIONHEADER }, - { "\\keyword", SECTIONHEADER }, - { "\\note", SECTIONHEADER }, - { "\\references", SECTIONHEADER }, - - { "\\section", SECTIONHEADER2 }, - { "\\seealso", SECTIONHEADER }, - { "\\source", SECTIONHEADER }, - { "\\title", SECTIONHEADER }, - - /* These sections contain R-like text */ - - { "\\examples",RSECTIONHEADER }, - { "\\usage", RSECTIONHEADER }, - - /* These sections contain verbatim text */ - - { "\\alias", VSECTIONHEADER }, - { "\\name", VSECTIONHEADER }, - { "\\synopsis",VSECTIONHEADER }, - { "\\Rdversion",VSECTIONHEADER }, - - /* These macros take no arguments. One character non-alpha escapes get the - same token value */ - - { "\\cr", ESCAPE }, - { "\\dots", ESCAPE }, - { "\\ldots", ESCAPE }, - { "\\R", ESCAPE }, - { "\\tab", ESCAPE }, - - /* These macros take one LaTeX-like argument. */ - - { "\\acronym", LATEXMACRO }, - { "\\bold", LATEXMACRO }, - { "\\cite", LATEXMACRO }, - { "\\command", LATEXMACRO }, - { "\\dfn", LATEXMACRO }, - { "\\dQuote", LATEXMACRO }, - { "\\email", LATEXMACRO }, - - { "\\emph", LATEXMACRO }, - { "\\file", LATEXMACRO }, - { "\\linkS4class", LATEXMACRO }, - { "\\pkg", LATEXMACRO }, - { "\\sQuote", LATEXMACRO }, - - { "\\strong", LATEXMACRO }, - - { "\\var", LATEXMACRO }, - - /* These are like SECTIONHEADER/LATEXMACRO, but they change the interpretation of \item */ - - { "\\arguments",LISTSECTION }, - { "\\value", LISTSECTION }, - - { "\\describe",DESCRIPTION }, - { "\\enumerate",ITEMIZE }, - { "\\itemize", ITEMIZE }, - - { "\\item", NOITEM }, /* will change to UNKNOWN, ESCAPE, or LATEXMACRO2 depending on context */ - - /* These macros take two LaTeX-like arguments. */ - - { "\\enc", LATEXMACRO2 }, - { "\\if", LATEXMACRO2 }, - { "\\method", LATEXMACRO2 }, - { "\\S3method",LATEXMACRO2 }, - { "\\S4method",LATEXMACRO2 }, - { "\\tabular", LATEXMACRO2 }, - { "\\subsection", LATEXMACRO2 }, - - /* This macro takes one verbatim and one LaTeX-like argument. */ - - { "\\href", VERBLATEX }, - - /* This macro takes three LaTeX-like arguments. */ - - { "\\ifelse", LATEXMACRO3 }, - - /* These macros take one optional bracketed option and always take - one LaTeX-like argument */ - - { "\\link", OPTMACRO }, - - /* These markup macros require an R-like text argument */ - - { "\\code", RCODEMACRO }, - { "\\dontshow",RCODEMACRO }, - { "\\donttest",RCODEMACRO }, - { "\\testonly",RCODEMACRO }, - - /* This macro takes one optional bracketed option and one R-like argument */ - - { "\\Sexpr", SEXPR }, - - /* This is just like a VSECTIONHEADER, but it needs SEXPR processing */ - - { "\\RdOpts", RDOPTS }, - - /* These macros take one verbatim arg and ignore everything except braces */ - - { "\\dontrun", VERBMACRO }, /* at least for now */ - { "\\env", VERBMACRO }, - { "\\kbd", VERBMACRO }, - { "\\option", VERBMACRO }, - { "\\out", VERBMACRO }, - { "\\preformatted", VERBMACRO }, - - { "\\samp", VERBMACRO }, - { "\\special", VERBMACRO }, - { "\\url", VERBMACRO }, - { "\\verb", VERBMACRO }, - - /* These ones take one or two verbatim args */ - - { "\\eqn", VERBMACRO2 }, - { "\\deqn", VERBMACRO2 }, - { "\\figure", VERBMACRO2 }, - - /* We parse IFDEF/IFNDEF as markup, not as a separate preprocessor step */ - - { "#ifdef", IFDEF }, - { "#ifndef", IFDEF }, - { "#endif", ENDIF }, - - /* These allow user defined macros */ - { "\\newcommand", NEWCOMMAND }, - { "\\renewcommand", NEWCOMMAND }, - - { 0, 0 } - /* All other markup macros are rejected. */ -}; - -/* Record the longest # directive here */ -#define DIRECTIVE_LEN 7 - -static SEXP InstallKeywords() -{ - int i, num; - SEXP result, name, val; - num = sizeof(keywords)/sizeof(keywords[0]); - PROTECT(result = R_NewHashedEnv(R_EmptyEnv, ScalarInteger(num))); - for (i = 0; keywords[i].name; i++) { - PROTECT(name = install(keywords[i].name)); - PROTECT(val = ScalarInteger(keywords[i].token)); - defineVar(name, val, result); - UNPROTECT(2); - } - UNPROTECT(1); - return result; -} - -static int KeywordLookup(const char *s) -{ - SEXP rec = findVar(install(s), parseState.xxMacroList); - if (rec == R_UnboundValue) return UNKNOWN; - else return INTEGER(rec)[0]; -} - -static SEXP UserMacroLookup(const char *s) -{ - SEXP rec = findVar(install(s), parseState.xxMacroList); - if (rec == R_UnboundValue) error(_("Unable to find macro %s"), s); - PROTECT(rec); - SEXP res = getAttrib(rec, install("definition")); - UNPROTECT(1); - return res; -} - -static void yyerror(const char *s) -{ - static const char *const yytname_translations[] = - { - /* the left column are strings coming from bison, the right - column are translations for users. - The first YYENGLISH from the right column are English to be translated, - the rest are to be copied literally. The #if 0 block below allows xgettext - to see these. - */ -#define YYENGLISH 17 - "$undefined", "input", - "SECTIONHEADER","section header", - "RSECTIONHEADER","section header", - "VSECTIONHEADER","section header", - "LISTSECTION", "section header", - - "LATEXMACRO", "macro", - "LATEXMACRO2", "macro", - "LATEXMACRO3", "macro", - "RCODEMACRO", "macro", - "VERBMACRO", "macro", - "VERBMACRO2", "macro", - - "ESCAPE", "macro", - "ITEMIZE", "macro", - "IFDEF", "conditional", - "SECTIONHEADER2","section header", - "OPTMACRO", "macro", - - "DESCRIPTION", "macro", - "VERB", "VERBATIM TEXT", - 0, 0 - }; - static char const yyunexpected[] = "syntax error, unexpected "; - static char const yyexpecting[] = ", expecting "; - static char const yyshortunexpected[] = "unexpected %s"; - static char const yylongunexpected[] = "unexpected %s '%s'"; - char *expecting; - char ParseErrorMsg[PARSE_ERROR_SIZE]; - SEXP filename; - char ParseErrorFilename[PARSE_ERROR_SIZE]; - - xxWarnNewline(); /* post newline warning if necessary */ - - /* - R_ParseError = yylloc.first_line; - R_ParseErrorCol = yylloc.first_column; - R_ParseErrorFile = SrcFile; - */ - - if (!strncmp(s, yyunexpected, sizeof yyunexpected -1)) { - int i, translated = FALSE; - /* Edit the error message */ - expecting = strstr(s + sizeof yyunexpected -1, yyexpecting); - if (expecting) *expecting = '\0'; - for (i = 0; yytname_translations[i]; i += 2) { - if (!strcmp(s + sizeof yyunexpected - 1, yytname_translations[i])) { - if (yychar < 256) - snprintf(ParseErrorMsg, PARSE_ERROR_SIZE, - _(yyshortunexpected), - i/2 < YYENGLISH ? _(yytname_translations[i+1]) - : yytname_translations[i+1]); - else - snprintf(ParseErrorMsg, PARSE_ERROR_SIZE, - _(yylongunexpected), - i/2 < YYENGLISH ? _(yytname_translations[i+1]) - : yytname_translations[i+1], - CHAR(STRING_ELT(yylval, 0))); - translated = TRUE; - break; - } - } - if (!translated) { - if (yychar < 256) - snprintf(ParseErrorMsg, PARSE_ERROR_SIZE, _(yyshortunexpected), - s + sizeof yyunexpected - 1); - else - snprintf(ParseErrorMsg, PARSE_ERROR_SIZE, _(yylongunexpected), - s + sizeof yyunexpected - 1, CHAR(STRING_ELT(yylval, 0))); - } - if (expecting) { - translated = FALSE; - for (i = 0; yytname_translations[i]; i += 2) { - if (!strcmp(expecting + sizeof yyexpecting - 1, yytname_translations[i])) { - strcat(ParseErrorMsg, _(yyexpecting)); - strcat(ParseErrorMsg, i/2 < YYENGLISH ? _(yytname_translations[i+1]) - : yytname_translations[i+1]); - translated = TRUE; - break; - } - } - if (!translated) { - strcat(ParseErrorMsg, _(yyexpecting)); - strcat(ParseErrorMsg, expecting + sizeof yyexpecting - 1); - } - } - } else if (!strncmp(s, yyunknown, sizeof yyunknown-1)) { - snprintf(ParseErrorMsg, PARSE_ERROR_SIZE, - "%s '%s'", s, CHAR(STRING_ELT(yylval, 0))); - } else { - snprintf(ParseErrorMsg, PARSE_ERROR_SIZE, "%s", s); - } - filename = findVar(install("filename"), SrcFile); - if (isString(filename) && length(filename)) - strncpy(ParseErrorFilename, CHAR(STRING_ELT(filename, 0)), PARSE_ERROR_SIZE - 1); - else - ParseErrorFilename[0] = '\0'; - if (wCalls) { - if (yylloc.first_line != yylloc.last_line) - warning("%s:%d-%d: %s", - ParseErrorFilename, yylloc.first_line, yylloc.last_line, ParseErrorMsg); - else - warning("%s:%d: %s", - ParseErrorFilename, yylloc.first_line, ParseErrorMsg); - } else { - if (yylloc.first_line != yylloc.last_line) - warningcall(R_NilValue, "%s:%d-%d: %s", - ParseErrorFilename, yylloc.first_line, yylloc.last_line, ParseErrorMsg); - else - warningcall(R_NilValue, "%s:%d: %s", - ParseErrorFilename, yylloc.first_line, ParseErrorMsg); - } -} - -#define TEXT_PUSH(c) do { \ - size_t nc = bp - stext; \ - if (nc >= nstext - 1) { \ - char *old = stext; \ - nstext *= 2; \ - stext = malloc(nstext); \ - if(!stext) error(_("unable to allocate buffer for long string at line %d"), parseState.xxlineno);\ - memmove(stext, old, nc); \ - if(old != st0) free(old); \ - bp = stext+nc; } \ - *bp++ = ((char) c); \ -} while(0) - -static void setfirstloc(void) -{ - yylloc.first_line = parseState.xxlineno; - yylloc.first_column = parseState.xxcolno; - yylloc.first_byte = parseState.xxbyteno; -} - -static void setlastloc(void) -{ - yylloc.last_line = prevlines[prevpos]; - yylloc.last_column = prevcols[prevpos]; - yylloc.last_byte = prevbytes[prevpos]; -} - -/* Split the input stream into tokens. */ -/* This is the lowest of the parsing levels. */ - -static int token(void) -{ - int c, lookahead; - int outsideLiteral = parseState.xxmode == LATEXLIKE || parseState.xxmode == INOPTION || parseState.xxbraceDepth == 0; - - if (parseState.xxinitvalue) { - yylloc.first_line = 0; - yylloc.first_column = 0; - yylloc.first_byte = 0; - yylloc.last_line = 0; - yylloc.last_column = 0; - yylloc.last_byte = 0; - PROTECT(yylval = mkString("")); - c = parseState.xxinitvalue; - parseState.xxinitvalue = 0; - return(c); - } - - setfirstloc(); - c = xxgetc(); - - switch (c) { - case '%': if (!parseState.xxinEqn) return mkComment(c); - break; - case '\\': - if (!parseState.xxinEqn) { - lookahead = xxungetc(xxgetc()); - if (isalpha(lookahead) && parseState.xxmode != VERBATIM - /* In R strings, only link or var is allowed as markup */ - && (lookahead == 'l' || lookahead == 'v' || !parseState.xxinRString)) - return mkMarkup(c); - } - break; - case R_EOF: - if (parseState.xxinRString) { - xxWarnNewline(); - error(_("Unexpected end of input (in %c quoted string opened at %s:%d:%d)"), - parseState.xxinRString, parseState.xxBasename, parseState.xxQuoteLine, parseState.xxQuoteCol); - } - return END_OF_INPUT; - case '#': - if (!parseState.xxinEqn && yylloc.first_column == 1) return mkIfdef(c); - break; - case LBRACE: - if (!parseState.xxinRString) { - parseState.xxbraceDepth++; - if (outsideLiteral) return c; - } - break; - case RBRACE: - if (!parseState.xxinRString) { - parseState.xxbraceDepth--; - if (outsideLiteral || parseState.xxbraceDepth == 0) return c; - } - break; - case '[': - case ']': - if (parseState.xxmode == INOPTION ) return c; - break; - } - - switch (parseState.xxmode) { - case RLIKE: return mkCode(c); - case INOPTION: - case LATEXLIKE: return mkText(c); - case VERBATIM: return mkVerb(c); - } - - return ERROR; /* We shouldn't get here. */ -} - -#define INITBUFSIZE 128 - -static int mkText(int c) -{ - char st0[INITBUFSIZE]; - unsigned int nstext = INITBUFSIZE; - char *stext = st0, *bp = st0, lookahead; - - while(1) { - switch (c) { - case '\\': - lookahead = (char) xxgetc(); - if (lookahead == LBRACE || lookahead == RBRACE || - lookahead == '%' || lookahead == '\\') { - c = lookahead; - break; - } - xxungetc(lookahead); - if (isalpha(lookahead)) goto stop; - case ']': - if (parseState.xxmode == INOPTION) goto stop; - break; - case '%': - case LBRACE: - case RBRACE: - case R_EOF: - goto stop; - } - TEXT_PUSH(c); - if (c == '\n') goto stop; - c = xxgetc(); - }; -stop: - if (c != '\n') xxungetc(c); /* newline causes a break, but we keep it */ - PROTECT(yylval = mkString2(stext, bp - stext)); - if(stext != st0) free(stext); - return TEXT; -} - -static int mkComment(int c) -{ - char st0[INITBUFSIZE]; - unsigned int nstext = INITBUFSIZE; - char *stext = st0, *bp = st0; - - do TEXT_PUSH(c); - while ((c = xxgetc()) != '\n' && c != R_EOF); - - xxungetc(c); - - PROTECT(yylval = mkString2(stext, bp - stext)); - if(stext != st0) free(stext); - return COMMENT; -} - -static int mkCode(int c) -{ - char st0[INITBUFSIZE]; - unsigned int nstext = INITBUFSIZE; - char *stext = st0, *bp = st0; - - /* Avoid double counting initial braces */ - if (c == LBRACE && !parseState.xxinRString) parseState.xxbraceDepth--; - if (c == RBRACE && !parseState.xxinRString) parseState.xxbraceDepth++; - - while(1) { - int escaped = 0; - if (c == '\\') { - int lookahead = xxgetc(); - if (lookahead == '\\' || lookahead == '%') { - c = lookahead; - escaped = 1; - } else xxungetc(lookahead); - } - if ((!escaped && c == '%') || c == R_EOF) break; - if (parseState.xxinRString) { - /* This stuff is messy, because there are two levels of escaping: - The Rd escaping and the R code string escaping. */ - if (c == '\\') { - int lookahead = xxgetc(); - if (lookahead == '\\') { /* This must be the 3rd backslash */ - lookahead = xxgetc(); - if (lookahead == parseState.xxinRString || lookahead == '\\') { - TEXT_PUSH(c); - c = lookahead; - escaped = 1; - } else { - xxungetc(lookahead); /* put back the 4th char */ - xxungetc('\\'); /* and the 3rd */ - } - } else if (lookahead == parseState.xxinRString) { /* There could be one or two before this */ - TEXT_PUSH(c); - c = lookahead; - escaped = 1; - } else if (!escaped && (lookahead == 'l' || lookahead == 'v')) { - /* assume \link or \var; this breaks vertical tab, but does anyone ever use that? */ - xxungetc(lookahead); - break; - } else xxungetc(lookahead); - } - if (!escaped && c == parseState.xxinRString) - parseState.xxinRString = 0; - } else { - if (c == '#') { - do { - int escaped = 0; - TEXT_PUSH(c); - c = xxgetc(); - if (c == '\\') { - int lookahead = xxgetc(); - if (lookahead == '\\' || lookahead == '%' || lookahead == LBRACE || lookahead == RBRACE) { - c = lookahead; - escaped = 1; - } else xxungetc(lookahead); - } - if (c == LBRACE && !escaped) parseState.xxbraceDepth++; - else if (c == RBRACE && !escaped) parseState.xxbraceDepth--; - } while (c != '\n' && c != R_EOF && parseState.xxbraceDepth > 0); - if (c == RBRACE && !escaped) parseState.xxbraceDepth++; /* avoid double counting */ - } - if (c == '\'' || c == '"' || c == '`') { - parseState.xxinRString = c; - parseState.xxQuoteLine = parseState.xxlineno; - parseState.xxQuoteCol = parseState.xxcolno; - } else if (c == '\\' && !escaped) { - int lookahead = xxgetc(); - if (lookahead == LBRACE || lookahead == RBRACE) { - c = lookahead; - } else if (isalpha(lookahead)) { - xxungetc(lookahead); - c = '\\'; - break; - } else { - TEXT_PUSH('\\'); - c = lookahead; - } - } else if (c == LBRACE) { - parseState.xxbraceDepth++; - } else if (c == RBRACE) { - if (parseState.xxbraceDepth == 1) break; - else parseState.xxbraceDepth--; - } else if (c == R_EOF) break; - } - TEXT_PUSH(c); - if (c == '\n') { - if (parseState.xxinRString && !parseState.xxNewlineInString) - parseState.xxNewlineInString = parseState.xxlineno-1; - break; - } - c = xxgetc(); - } - if (c != '\n') xxungetc(c); - PROTECT(yylval = mkString2(stext, bp - stext)); - if(stext != st0) free(stext); - return RCODE; -} - -static int mkMarkup(int c) -{ - char st0[INITBUFSIZE]; - unsigned int nstext = INITBUFSIZE; - char *stext = st0, *bp = st0; - int retval = 0, attempt = 0; - - TEXT_PUSH(c); - while (isalnum((c = xxgetc()))) TEXT_PUSH(c); - - while (attempt++ < 2) { - /* character escapes are processed as text, not markup */ - if (bp == stext+1) { - TEXT_PUSH(c); - TEXT_PUSH('\0'); - retval = TEXT; - c = xxgetc(); - break; - } else { - TEXT_PUSH('\0'); - retval = KeywordLookup(stext); - if (retval == UNKNOWN && attempt == 1) { /* try again, non-digits only */ - bp--; /* pop the \0 */ - while (isdigit(*(bp-1))) { - xxungetc(c); - c = *(--bp); /* pop the last letter into c */ - } - } else { - if (retval == NOITEM) - retval = parseState.xxitemType; - break; - } - } - } - PROTECT(yylval = mkString2(stext, bp - stext - 1)); - if(stext != st0) free(stext); - xxungetc(c); - return retval; -} - -static int mkIfdef(int c) -{ - char st0[INITBUFSIZE]; - unsigned int nstext = INITBUFSIZE; - char *stext = st0, *bp = st0; - int retval; - - TEXT_PUSH(c); - while (isalpha((c = xxgetc())) && bp - stext <= DIRECTIVE_LEN) TEXT_PUSH(c); - TEXT_PUSH('\0'); - xxungetc(c); - - retval = KeywordLookup(stext); - PROTECT(yylval = mkString2(stext, bp - stext - 1)); - - switch (retval) { - case ENDIF: /* eat chars to the end of the line */ - do { c = xxgetc(); } - while (c != '\n' && c != R_EOF); - break; - case UNKNOWN: - UNPROTECT(1); - bp--; bp--; - for (; bp > stext; bp--) - xxungetc(*bp); - switch (parseState.xxmode) { - case RLIKE: - retval = mkCode(*bp); - break; - case INOPTION: - case LATEXLIKE: - retval = mkText(*bp); - break; - case VERBATIM: - retval = mkVerb(*bp); - break; - } - break; - } - if(stext != st0) free(stext); - return retval; -} - -static int mkVerb(int c) -{ - char st0[INITBUFSIZE]; - unsigned int nstext = INITBUFSIZE; - char *stext = st0, *bp = st0; - - /* Avoid double counting initial braces */ - if (c == LBRACE) parseState.xxbraceDepth--; - if (c == RBRACE) parseState.xxbraceDepth++; - - while(1) { - int escaped = 0; - if (c == '\\') { - int lookahead = xxgetc(); - if (lookahead == '\\' || lookahead == '%' || lookahead == LBRACE || lookahead == RBRACE) { - escaped = 1; - if (parseState.xxinEqn) TEXT_PUSH(c); - c = lookahead; - } else xxungetc(lookahead); - } - if (c == R_EOF) break; - if (!escaped) { - if (c == '%' && !parseState.xxinEqn) break; - else if (c == LBRACE) parseState.xxbraceDepth++; - else if (c == RBRACE) { - if (parseState.xxbraceDepth == 1) break; - else parseState.xxbraceDepth--; - } - } - TEXT_PUSH(c); - if (c == '\n') break; - c = xxgetc(); - }; - if (c != '\n') xxungetc(c); - PROTECT(yylval = mkString2(stext, bp - stext)); - if(stext != st0) free(stext); - return VERB; -} - -static int yylex(void) -{ - int tok = token(); - - if (parseState.xxDebugTokens) { - Rprintf("%d:%d: %s", yylloc.first_line, yylloc.first_column, yytname[YYTRANSLATE(tok)]); - if (parseState.xxinRString) Rprintf("(in %c%c)", parseState.xxinRString, parseState.xxinRString); - if (tok > 255 && tok != END_OF_INPUT) - Rprintf(": %s", CHAR(STRING_ELT(yylval, 0))); - Rprintf("\n"); - } - setlastloc(); - return tok; -} - -static void PutState(ParseState *state) { - state->xxinRString = parseState.xxinRString; - state->xxQuoteLine = parseState.xxQuoteLine; - state->xxQuoteCol = parseState.xxQuoteCol; - state->xxinEqn = parseState.xxinEqn; - state->xxNewlineInString = parseState.xxNewlineInString; - state->xxlineno = parseState.xxlineno; - state->xxbyteno = parseState.xxbyteno; - state->xxcolno = parseState.xxcolno; - state->xxmode = parseState.xxmode; - state->xxitemType = parseState.xxitemType; - state->xxbraceDepth = parseState.xxbraceDepth; - state->xxDebugTokens = parseState.xxDebugTokens; - state->xxBasename = parseState.xxBasename; - state->Value = parseState.Value; - state->xxinitvalue = parseState.xxinitvalue; - state->xxMacroList = parseState.xxMacroList; - state->prevState = parseState.prevState; -} - -static void UseState(ParseState *state) { - parseState.xxinRString = state->xxinRString; - parseState.xxQuoteLine = state->xxQuoteLine; - parseState.xxQuoteCol = state->xxQuoteCol; - parseState.xxinEqn = state->xxinEqn; - parseState.xxNewlineInString = state->xxNewlineInString; - parseState.xxlineno = state->xxlineno; - parseState.xxbyteno = state->xxbyteno; - parseState.xxcolno = state->xxcolno; - parseState.xxmode = state->xxmode; - parseState.xxitemType = state->xxitemType; - parseState.xxbraceDepth = state->xxbraceDepth; - parseState.xxDebugTokens = state->xxDebugTokens; - parseState.xxBasename = state->xxBasename; - parseState.Value = state->Value; - parseState.xxinitvalue = state->xxinitvalue; - parseState.xxMacroList = state->xxMacroList; - parseState.prevState = state->prevState; -} - -static void PushState() { - if (busy) { - ParseState *prev = malloc(sizeof(ParseState)); - PutState(prev); - parseState.prevState = prev; - } else - parseState.prevState = NULL; - busy = TRUE; -} - -static void PopState() { - if (parseState.prevState) { - ParseState *prev = parseState.prevState; - UseState(prev); - free(prev); - } else - busy = FALSE; -} - -/* "do_parseRd" - - .External2(C_parseRd,file, srcfile, encoding, verbose, basename, warningCalls) - If there is text then that is read and the other arguments are ignored. - - This is derived fron the function of the same name in the GnuR version. - Argument checking has already been performed, however, the types of the - arguments are as per the GnuR version, just passed explicitly (.Call style) - rather then as a list. -*/ -SEXP C_parseRd(SEXP con, SEXP source, SEXP verbose, SEXP fragment, SEXP basename, SEXP warningcalls, SEXP macros, SEXP warnDupsArg) { - SEXP s = R_NilValue; - ParseStatus status; - -#if DEBUGMODE - yydebug = 1; -#endif - - R_ParseError = 0; - R_ParseErrorMsg[0] = '\0'; - - PushState(); - -// parseState.xxDebugTokens = asInteger(verbose); - parseState.xxBasename = CHAR(STRING_ELT(basename, 0)); - wCalls = asLogical(warningcalls); - warnDups = asLogical(warnDupsArg); - - s = R_ParseRd(con, &status, source, asLogical(fragment), macros); - PopState(); - if (status != PARSE_OK) { - // TODO throw an exception - } - return s; -} - -/* "do_deparseRd" - - .External2(C_deparseRd, element, state) -*/ - -// TODO diff --git a/com.oracle.truffle.r.native/library/tools/src/gramRd_fastr.h b/com.oracle.truffle.r.native/library/tools/src/gramRd_fastr.h new file mode 100644 index 0000000000000000000000000000000000000000..484c68e964e8149684afcc5604cf32b636fe23fe --- /dev/null +++ b/com.oracle.truffle.r.native/library/tools/src/gramRd_fastr.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016, 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. + */ +#ifndef GRAMRD_FASTR_H +#define GRAMRD_FASTR_H + +int callGetCMethod(void *conn); + +#endif //GRAMRD_FASTR_H diff --git a/com.oracle.truffle.r.native/osextras/src/doglob.c b/com.oracle.truffle.r.native/library/tools/src/gramRd_jni.c similarity index 56% rename from com.oracle.truffle.r.native/osextras/src/doglob.c rename to com.oracle.truffle.r.native/library/tools/src/gramRd_jni.c index a26e7f67eac0d6d3b29e98627b9efe51e9752523..c109bff1be15b1e26777045b48b43e0f87bc186f 100644 --- a/com.oracle.truffle.r.native/osextras/src/doglob.c +++ b/com.oracle.truffle.r.native/library/tools/src/gramRd_jni.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -20,28 +20,23 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -#include <string.h> -#include <glob.h> +#include "gramRd_fastr.h" #include <jni.h> -static jmethodID addPathID = 0; +extern JNIEnv *getEnv(); -JNIEXPORT void JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1Glob_doglob(JNIEnv *env, jobject obj, jstring pattern) { - glob_t globstruct; +static jmethodID getcMethodID = NULL; - if (addPathID == 0) { - addPathID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, obj), "addPath", "(Ljava/lang/String;)V"); - } +static void findGetCMethod(JNIEnv *env) { + jclass klass = (*env)->FindClass(env, "com/oracle/truffle/r/runtime/conn/RConnection"); + getcMethodID = (*env)->GetMethodID(env, klass, "getc", "()I"); +} - const char *patternChars = (*env)->GetStringUTFChars(env, pattern, NULL); - int rc = glob(patternChars, 0, NULL, &globstruct); - if (rc == 0) { - int i; - for (i = 0; i < globstruct.gl_pathc; i++) { - char *path = globstruct.gl_pathv[i]; - jstring pathString = (*env)->NewStringUTF(env, path); - (*env)->CallVoidMethod(env, obj, addPathID, pathString); - } +int callGetCMethod(void *conn) { + JNIEnv *env = getEnv(); + if (getcMethodID == NULL) { + findGetCMethod(env); } + int c = (*env)->CallIntMethod(env, conn, getcMethodID, conn); + return c; } diff --git a/com.oracle.truffle.r.native/osextras/src/getutsname.c b/com.oracle.truffle.r.native/osextras/src/getutsname.c deleted file mode 100644 index a676f8545b0850ebecb0e92412c64c4231214ba8..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.native/osextras/src/getutsname.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * 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 <sys/utsname.h> -#include <jni.h> - -struct utsname name; - -static jfieldID checkGetFieldID(JNIEnv *env, jclass klass, const char *name, const char *sig) { - jfieldID fieldID = (*env)->GetFieldID(env, klass, name, sig); - if (fieldID == NULL) { - char buf[1024]; - strcpy(buf, "failed to find field "); - strcat(buf, name); - (*env)->FatalError(env, buf); - } - return fieldID; -} - -JNIEXPORT void JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1UtsName_getutsname(JNIEnv *env, jobject obj) { - uname(&name); - jstring sysname = (*env)->NewStringUTF(env, name.sysname); - jstring release = (*env)->NewStringUTF(env, name.release); - jstring version = (*env)->NewStringUTF(env, name.version); - jstring machine = (*env)->NewStringUTF(env, name.machine); - jstring nodename = (*env)->NewStringUTF(env, name.nodename); - - jclass klass = (*env)->GetObjectClass(env, obj); - - jfieldID sysnameId = checkGetFieldID(env, klass, "sysname", "Ljava/lang/String;"); - jfieldID releaseId = checkGetFieldID(env, klass, "release", "Ljava/lang/String;"); - jfieldID versionId = checkGetFieldID(env, klass, "version", "Ljava/lang/String;"); - jfieldID machineId = checkGetFieldID(env, klass, "machine", "Ljava/lang/String;"); - jfieldID nodenameId = checkGetFieldID(env, klass, "nodename", "Ljava/lang/String;"); - - (*env)->SetObjectField(env, obj, sysnameId, sysname); - (*env)->SetObjectField(env, obj, releaseId, release); - (*env)->SetObjectField(env, obj, versionId, version); - (*env)->SetObjectField(env, obj, machineId, machine); - (*env)->SetObjectField(env, obj, nodenameId, nodename); - -} diff --git a/com.oracle.truffle.r.native/run/Makefile b/com.oracle.truffle.r.native/run/Makefile index b445653a8b170c4f793c62fc5d44ed3e4ffc2d89..8d0b3687120d49b52006a99541182b95c1970cdf 100644 --- a/com.oracle.truffle.r.native/run/Makefile +++ b/com.oracle.truffle.r.native/run/Makefile @@ -44,7 +44,7 @@ FASTR_SHARE_DIR := $(FASTR_R_HOME)/share FASTR_INCLUDE_DIR := $(FASTR_R_HOME)/include R_SCRIPT := $(addprefix $(GNUR_HOME)/bin/,R) -SUPPORT_SCRIPTS := $(addprefix $(GNUR_HOME)/bin/,BATCH COMPILE INSTALL SHLIB Rcmd config javareconf) +BIN_FILES := $(wildcard $(GNUR_HOME)/bin/*) DOC_FILES := $(wildcard $(GNUR_HOME)/doc/*) @@ -66,18 +66,20 @@ rundirs: rcmds: $(FASTR_BIN_DIR)/R $(FASTR_BIN_DIR)/R: Makefile R.sh Rscript.sh Rscript_exec.sh Rclasspath.sh + cp -r $(BIN_FILES) $(FASTR_BIN_DIR) + # overide bin/R cp R.sh $(FASTR_BIN_DIR)/exec/R + # override bin/Rscript cp Rscript_exec.sh $(FASTR_BIN_DIR)/execRextras/Rscript cp Rscript.sh $(FASTR_BIN_DIR)/Rscript + # for embedded support cp Rclasspath.sh $(FASTR_BIN_DIR)/execRextras/Rclasspath chmod +x $(FASTR_BIN_DIR)/exec/R $(FASTR_BIN_DIR)/execRextras/Rscript $(FASTR_BIN_DIR)/Rscript $(FASTR_BIN_DIR)/execRextras/Rclasspath - cp $(SUPPORT_SCRIPTS) $(FASTR_BIN_DIR) + # update R_HOME_DIR to FastR sed -e 's!^\(R_HOME_DIR=\)\(.*\)!\1"$(FASTR_R_HOME)"!' < $(R_SCRIPT) > $(FASTR_BIN_DIR)/R chmod +x $(FASTR_BIN_DIR)/R touch $(FASTR_ETC_DIR)/ldpaths sed -e "s|\(R_LIBS_USER=.*-'\)\(.*\)'}|\1$(FASTR_R_HOME)/library'}|" < $(GNUR_HOME)/etc/Renviron > $(FASTR_ETC_DIR)/Renviron - # set R_INSTALL_TAR - ed $(FASTR_ETC_DIR)/Renviron < edRenviron cp $(GNUR_HOME)/etc/Makeconf Makeconf.etc cp $(GNUR_HOME)/etc/javaconf $(FASTR_ETC_DIR)/javaconf cp $(GNUR_HOME)/etc/repositories $(FASTR_ETC_DIR)/repositories diff --git a/com.oracle.truffle.r.native/run/edRenviron b/com.oracle.truffle.r.native/run/edRenviron deleted file mode 100644 index ea7921613517d5a33a6db9757618babbe78c2be9..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.native/run/edRenviron +++ /dev/null @@ -1,6 +0,0 @@ -/### Local/ -i -R_INSTALL_TAR=${TAR} -. -w -q diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java index 874e70cffb9c4222c2b0e437b78c80d7cf1c51ad..1117bfeece8340945f3593d5be80341087018b20 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java @@ -39,6 +39,7 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.ResourceHandlerFactory; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.builtins.RSpecialFactory; import com.oracle.truffle.r.runtime.context.Engine.ParseException; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.nodes.RNode; @@ -156,12 +157,16 @@ public abstract class RBuiltinPackage { } protected void add(Class<?> builtinClass, Function<RNode[], RBuiltinNode> constructor) { + add(builtinClass, constructor, null); + } + + protected void add(Class<?> builtinClass, Function<RNode[], RBuiltinNode> constructor, RSpecialFactory specialCall) { RBuiltin annotation = builtinClass.getAnnotation(RBuiltin.class); String[] parameterNames = annotation.parameterNames(); parameterNames = Arrays.stream(parameterNames).map(n -> n.isEmpty() ? null : n).toArray(String[]::new); ArgumentsSignature signature = ArgumentsSignature.get(parameterNames); putBuiltin(new RBuiltinFactory(annotation.name(), builtinClass, annotation.visibility(), annotation.aliases(), annotation.kind(), signature, annotation.nonEvalArgs(), annotation.splitCaller(), - annotation.alwaysSplit(), annotation.dispatch(), constructor, annotation.behavior())); + annotation.alwaysSplit(), annotation.dispatch(), constructor, annotation.behavior(), specialCall)); } } 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 bac47c0d9e2e6790b2b6dbec2659903aa73661fe..472fdc3f53b299f573acac83050b028769cddef2 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 @@ -10,24 +10,35 @@ */ 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.complexValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; +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.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; 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.builtin.CastBuilder; 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; +import com.oracle.truffle.r.runtime.data.RAttributeProfiles; +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.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; -//TODO: Implement permuting with DimNames +// TODO: add (permuted) dimnames to the result @RBuiltin(name = "aperm", kind = INTERNAL, parameterNames = {"a", "perm", "resize"}, behavior = PURE) public abstract class APerm extends RBuiltinNode { @@ -37,28 +48,26 @@ public abstract class APerm extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1); + casts.arg("a").mustNotBeNull(RError.Message.FIRST_ARG_MUST_BE_ARRAY); + casts.arg("perm").allowNull().mustBe(numericValue().or(stringValue()).or(complexValue())).mapIf(numericValue().or(complexValue()), asIntegerVector()); + casts.arg("resize").mustBe(numericValue().or(logicalValue()), Message.INVALID_LOGICAL, "resize").asLogicalVector().findFirst(); } - private void checkErrorConditions(RAbstractVector vector, byte resize) { + private void checkErrorConditions(RAbstractVector vector) { if (!vector.isArray()) { errorProfile.enter(); - throw RError.error(this, RError.Message.FIRST_ARG_MUST_BE_ARRAY); - } - if (resize == RRuntime.LOGICAL_NA) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_LOGICAL, "resize"); + throw RError.error(RError.SHOW_CALLER, RError.Message.FIRST_ARG_MUST_BE_ARRAY); } } @Specialization protected RAbstractVector aPerm(RAbstractVector vector, @SuppressWarnings("unused") RNull permVector, byte resize) { - checkErrorConditions(vector, resize); + checkErrorConditions(vector); int[] dim = vector.getDimensions(); final int diml = dim.length; - RVector result = vector.createEmptySameType(vector.getLength(), vector.isComplete()); + RVector<?> result = vector.createEmptySameType(vector.getLength(), vector.isComplete()); if (mustResize.profile(resize == RRuntime.LOGICAL_TRUE)) { int[] pDim = new int[diml]; @@ -93,7 +102,7 @@ public abstract class APerm extends RBuiltinNode { @Specialization protected RAbstractVector aPerm(RAbstractVector vector, RAbstractIntVector permVector, byte resize) { - checkErrorConditions(vector, resize); + checkErrorConditions(vector); int[] dim = vector.getDimensions(); int[] perm = getPermute(dim, permVector); @@ -101,7 +110,7 @@ public abstract class APerm extends RBuiltinNode { int[] posV = new int[dim.length]; int[] pDim = applyPermute(dim, perm, false); - RVector result = vector.createEmptySameType(vector.getLength(), vector.isComplete()); + RVector<?> result = vector.createEmptySameType(vector.getLength(), vector.isComplete()); result.setDimensions(resize == RRuntime.LOGICAL_TRUE ? pDim : dim); @@ -115,6 +124,31 @@ public abstract class APerm extends RBuiltinNode { return result; } + @Specialization + protected RAbstractVector aPerm(RAbstractVector vector, RAbstractStringVector permVector, byte resize, + @Cached("create()") RAttributeProfiles dimNamesProfile) { + RList dimNames = vector.getDimNames(dimNamesProfile); + 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"); + } + + int[] perm = new int[permVector.getLength()]; + for (int i = 0; i < perm.length; i++) { + for (int dimNamesIdx = 0; dimNamesIdx < dimNames.getLength(); dimNamesIdx++) { + if (dimNames.getDataAt(dimNamesIdx).equals(permVector.getDataAt(i))) { + perm[i] = dimNamesIdx; + break; + } + } + // TODO: not found dimname error + } + + // Note: if this turns out to be slow, we can cache the permutation + return aPerm(vector, RDataFactory.createIntVector(perm, true), resize); + } + private static int[] getReverse(int[] dim) { int[] arrayPerm = new int[dim.length]; for (int i = 0; i < dim.length; i++) { @@ -136,13 +170,13 @@ public abstract class APerm extends RBuiltinNode { int pos = perm.getDataAt(i) - 1; // Adjust to zero based permute. if (pos >= perm.getLength() || pos < 0) { errorProfile.enter(); - throw RError.error(this, RError.Message.VALUE_OUT_OF_RANGE, "perm"); + throw RError.error(RError.SHOW_CALLER, RError.Message.VALUE_OUT_OF_RANGE, "perm"); } arrayPerm[i] = pos; if (visited[pos]) { // Duplicate dimension mapping in permute errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "perm"); + throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "perm"); } visited[pos] = true; } @@ -150,7 +184,7 @@ public abstract class APerm extends RBuiltinNode { } else { // perm size error errorProfile.enter(); - throw RError.error(this, RError.Message.IS_OF_WRONG_LENGTH, "perm", perm.getLength(), dim.length); + throw RError.error(RError.SHOW_CALLER, 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/All.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/All.java index aeae231f1a6706aa88f4b15024a01292f69372e6..a055c59ec8d41ace36318e02ac511ed07d1e4ca9 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/All.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/All.java @@ -25,99 +25,27 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.runtime.RDispatch.SUMMARY_GROUP_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.nodes.builtin.CastBuilder; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.unary.CastLogicalNode; -import com.oracle.truffle.r.nodes.unary.CastLogicalNodeGen; -import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.api.dsl.Fallback; +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.RLogicalVector; -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.RVector; /** * TODO: Added primitive {@code na.rm} support, but this code needs rewriting in the same manner as * {@link Any} and there is opportunity to share code. */ @RBuiltin(name = "all", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE) -public abstract class All extends RBuiltinNode { - - @Child private CastLogicalNode castLogicalNode; - - @Override - public Object[] getDefaultParameterValues() { - return new Object[]{RArgsValuesAndNames.EMPTY, RRuntime.LOGICAL_FALSE}; - } +public abstract class All extends Quantifier { @Override - protected void createCasts(CastBuilder casts) { - // casts.arg("...").mustBe(integerValue().or(logicalValue())).asLogicalVector(); - casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); + protected boolean emptyVectorResult() { + return true; } - @Specialization - protected byte all(byte value, @SuppressWarnings("unused") boolean naRm) { - return value; + @Fallback + @SuppressWarnings("unused") + protected byte op(Object vector, Object naRm) { + throw RInternalError.shouldNotReachHere(); } - @Specialization - protected byte all(RLogicalVector vector, boolean naRm) { - return accumulate(vector, naRm); - } - - @Specialization - protected byte all(@SuppressWarnings("unused") RNull vector, @SuppressWarnings("unused") boolean naRm) { - return RRuntime.LOGICAL_TRUE; - } - - @Specialization - protected byte all(@SuppressWarnings("unused") RMissing vector, @SuppressWarnings("unused") boolean naRm) { - return RRuntime.LOGICAL_TRUE; - } - - @Specialization - protected byte all(RArgsValuesAndNames args, boolean naRm) { - if (castLogicalNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castLogicalNode = insert(CastLogicalNodeGen.create(true, false, false)); - } - Object[] argValues = args.getArguments(); - for (Object argValue : argValues) { - byte result; - if (argValue instanceof RVector || argValue instanceof RSequence) { - result = accumulate((RLogicalVector) castLogicalNode.execute(argValue), naRm); - } else if (argValue == RNull.instance) { - result = RRuntime.LOGICAL_TRUE; - } else { - result = (byte) castLogicalNode.execute(argValue); - if (result == RRuntime.LOGICAL_NA && naRm) { - continue; - } - } - if (result != RRuntime.LOGICAL_TRUE) { - return result; - } - } - return RRuntime.LOGICAL_TRUE; - } - - private static byte accumulate(RLogicalVector vector, boolean naRm) { - for (int i = 0; i < vector.getLength(); i++) { - byte b = vector.getDataAt(i); - if (b == RRuntime.LOGICAL_NA && naRm) { - continue; - } - if (b != RRuntime.LOGICAL_TRUE) { - return b; - } - } - return RRuntime.LOGICAL_TRUE; - } } 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 70e3f59befe6762be709e18a834ab931dee2261f..905fb5e0d0e90b19380f9fc56fe0ee2f68a8d9fc 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 @@ -22,7 +22,6 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Any.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Any.java index 669b8bab732c5aea14e4c8ae877008c611ef0e6a..f610412b15a1c8140ad32c72e0dc76ada9620630 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Any.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Any.java @@ -26,113 +26,22 @@ import static com.oracle.truffle.r.runtime.RDispatch.SUMMARY_GROUP_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.CompilerDirectives; -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.r.nodes.builtin.CastBuilder; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.unary.CastLogicalNode; -import com.oracle.truffle.r.nodes.unary.CastLogicalNodeGen; -import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.api.dsl.Fallback; +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.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "any", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE) -public abstract class Any extends RBuiltinNode { - - protected static final int MAX_CACHED_LENGTH = 10; - - private final NACheck naCheck = NACheck.create(); - private final ConditionProfile naRmProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile trueBranch = BranchProfile.create(); - private final BranchProfile falseBranch = BranchProfile.create(); - - @Children private final CastLogicalNode[] castLogicalNode = new CastLogicalNode[MAX_CACHED_LENGTH]; +public abstract class Any extends Quantifier { @Override - public Object[] getDefaultParameterValues() { - return new Object[]{RArgsValuesAndNames.EMPTY, RRuntime.LOGICAL_FALSE}; + protected boolean emptyVectorResult() { + return false; } - @Override - protected void createCasts(CastBuilder casts) { - casts.toLogical(1); + @Fallback + @SuppressWarnings("unused") + protected byte op(Object vector, Object naRm) { + throw RInternalError.shouldNotReachHere(); } - @Specialization(limit = "1", guards = {"cachedLength == args.getLength()", "cachedLength < MAX_CACHED_LENGTH"}) - @ExplodeLoop - protected byte anyCachedLength(RArgsValuesAndNames args, byte naRm, // - @Cached("args.getLength()") int cachedLength) { - boolean profiledNaRm = naRmProfile.profile(naRm != RRuntime.LOGICAL_FALSE); - Object[] arguments = args.getArguments(); - - byte result = RRuntime.LOGICAL_FALSE; - for (int i = 0; i < cachedLength; i++) { - Object argValue = arguments[i]; - byte v = processArgument(argValue, i, profiledNaRm); - if (v == RRuntime.LOGICAL_TRUE) { - return RRuntime.LOGICAL_TRUE; - } else if (v == RRuntime.LOGICAL_NA) { - result = RRuntime.LOGICAL_NA; - } - } - return result; - } - - @Specialization(contains = "anyCachedLength") - protected byte any(RArgsValuesAndNames args, byte naRm) { - boolean profiledNaRm = naRmProfile.profile(naRm != RRuntime.LOGICAL_FALSE); - - byte result = RRuntime.LOGICAL_FALSE; - for (Object argValue : args.getArguments()) { - byte v = processArgument(argValue, 0, profiledNaRm); - if (v == RRuntime.LOGICAL_TRUE) { - return RRuntime.LOGICAL_TRUE; - } else if (v == RRuntime.LOGICAL_NA) { - result = RRuntime.LOGICAL_NA; - } - } - return result; - } - - private byte processArgument(Object argValue, int index, boolean profiledNaRm) { - byte result = RRuntime.LOGICAL_FALSE; - if (argValue != RNull.instance) { - if (castLogicalNode[index] == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castLogicalNode[index] = insert(CastLogicalNodeGen.create(true, false, false)); - } - Object castValue = castLogicalNode[index].execute(argValue); - if (castValue instanceof RAbstractLogicalVector) { - RAbstractLogicalVector vector = (RAbstractLogicalVector) castValue; - naCheck.enable(vector); - for (int i = 0; i < vector.getLength(); i++) { - byte b = vector.getDataAt(i); - if (!profiledNaRm && naCheck.check(b)) { - result = RRuntime.LOGICAL_NA; - } else if (b == RRuntime.LOGICAL_TRUE) { - trueBranch.enter(); - return RRuntime.LOGICAL_TRUE; - } - } - } else { - byte b = (byte) castValue; - naCheck.enable(true); - if (!profiledNaRm && naCheck.check(b)) { - result = RRuntime.LOGICAL_NA; - } else if (b == RRuntime.LOGICAL_TRUE) { - trueBranch.enter(); - return RRuntime.LOGICAL_TRUE; - } - } - } - falseBranch.enter(); - return result; - } } 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 65de607dba4d9a9dbec7644b0f3b59d72d49bd5b..f4ca1e913a23c8c978744c3bbdde9a521581b57c 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 @@ -22,6 +22,7 @@ */ 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.RDispatch.INTERNAL_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -30,6 +31,7 @@ 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.ValueProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.control.RLengthNode; import com.oracle.truffle.r.runtime.RRuntime; @@ -47,12 +49,31 @@ 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; -@RBuiltin(name = "anyNA", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE) +@RBuiltin(name = "anyNA", kind = PRIMITIVE, parameterNames = {"x", "recursive"}, dispatch = INTERNAL_GENERIC, behavior = PURE) public abstract class AnyNA extends RBuiltinNode { private final NACheck naCheck = NACheck.create(); - public abstract byte execute(VirtualFrame frame, Object value); + private final boolean recursionAllowed; + + protected AnyNA(boolean recursionAllowed) { + this.recursionAllowed = recursionAllowed; + } + + protected AnyNA() { + this(true); + } + + protected boolean isRecursionAllowed() { + return recursionAllowed; + } + + public abstract byte execute(VirtualFrame frame, Object value, boolean recursive); + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("recursive").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + } private static byte doScalar(boolean isNA) { return RRuntime.asLogical(isNA); @@ -74,84 +95,86 @@ public abstract class AnyNA extends RBuiltinNode { } @Specialization - protected byte isNA(byte value) { + protected byte isNA(byte value, @SuppressWarnings("unused") boolean recursive) { return doScalar(RRuntime.isNA(value)); } @Specialization - protected byte isNA(int value) { + protected byte isNA(int value, @SuppressWarnings("unused") boolean recursive) { return doScalar(RRuntime.isNA(value)); } @Specialization - protected byte isNA(double value) { + protected byte isNA(double value, @SuppressWarnings("unused") boolean recursive) { return doScalar(RRuntime.isNAorNaN(value)); } @Specialization - protected byte isNA(RComplex value) { + protected byte isNA(RComplex value, @SuppressWarnings("unused") boolean recursive) { return doScalar(RRuntime.isNA(value)); } @Specialization - protected byte isNA(String value) { + protected byte isNA(String value, @SuppressWarnings("unused") boolean recursive) { return doScalar(RRuntime.isNA(value)); } @Specialization - protected byte isNA(@SuppressWarnings("unused") RRaw value) { + @SuppressWarnings("unused") + protected byte isNA(RRaw value, boolean recursive) { return doScalar(false); } @Specialization - protected byte isNA(@SuppressWarnings("unused") RNull value) { + protected byte isNA(@SuppressWarnings("unused") RNull value, @SuppressWarnings("unused") boolean recursive) { return doScalar(false); } @Specialization - protected byte isNA(RAbstractIntVector vector) { + protected byte isNA(RAbstractIntVector vector, @SuppressWarnings("unused") boolean recursive) { return doVector(vector, (v, i) -> naCheck.check(v.getDataAt(i))); } @Specialization - protected byte isNA(RAbstractDoubleVector vector) { + protected byte isNA(RAbstractDoubleVector vector, @SuppressWarnings("unused") boolean recursive) { // since return doVector(vector, (v, i) -> naCheck.checkNAorNaN(v.getDataAt(i))); } @Specialization - protected byte isNA(RAbstractComplexVector vector) { + protected byte isNA(RAbstractComplexVector vector, @SuppressWarnings("unused") boolean recursive) { return doVector(vector, (v, i) -> naCheck.check(v.getDataAt(i))); } @Specialization - protected byte isNA(RAbstractStringVector vector) { + protected byte isNA(RAbstractStringVector vector, @SuppressWarnings("unused") boolean recursive) { return doVector(vector, (v, i) -> naCheck.check(v.getDataAt(i))); } @Specialization - protected byte isNA(RAbstractLogicalVector vector) { + protected byte isNA(RAbstractLogicalVector vector, @SuppressWarnings("unused") boolean recursive) { return doVector(vector, (v, i) -> naCheck.check(v.getDataAt(i))); } @Specialization - protected byte isNA(@SuppressWarnings("unused") RAbstractRawVector vector) { + protected byte isNA(@SuppressWarnings("unused") RAbstractRawVector vector, @SuppressWarnings("unused") boolean recursive) { return doScalar(false); } - protected AnyNA createRecursive() { - return AnyNANodeGen.create(null); + protected AnyNA createRecursive(boolean recursive) { + return AnyNANodeGen.create(recursive, null); } - @Specialization - protected byte isNA(VirtualFrame frame, RList list, // - @Cached("createRecursive()") AnyNA recursive, // - @Cached("createClassProfile()") ValueProfile elementProfile, // + @Specialization(guards = "isRecursionAllowed()") + protected byte isNA(VirtualFrame frame, RList list, boolean recursive, + @Cached("createRecursive(recursive)") AnyNA recursiveNode, + @Cached("createClassProfile()") ValueProfile elementProfile, @Cached("create()") RLengthNode length) { + for (int i = 0; i < list.getLength(); i++) { Object value = elementProfile.profile(list.getDataAt(i)); - if (length.executeInteger(frame, value) == 1) { - byte result = recursive.execute(frame, value); + if (length.executeInteger(frame, value) > 0) { + byte result = recursiveNode.execute(frame, value, recursive); if (result == RRuntime.LOGICAL_TRUE) { return RRuntime.LOGICAL_TRUE; } @@ -159,4 +182,10 @@ public abstract class AnyNA extends RBuiltinNode { } return RRuntime.LOGICAL_FALSE; } + + @Specialization(guards = "!isRecursionAllowed()") + @SuppressWarnings("unused") + protected byte isNA(VirtualFrame frame, RList list, boolean recursive) { + return RRuntime.LOGICAL_FALSE; + } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Arg.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Arg.java index 618c7c4b5f99ed26bab4713d06855088ad30c6ab..0dca5bbfb11818485db259a0242c9a93e83dfe94 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Arg.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Arg.java @@ -22,22 +22,68 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import static com.oracle.truffle.r.runtime.RDispatch.COMPLEX_GROUP_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.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; +import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "Arg", kind = PRIMITIVE, parameterNames = {"z"}, dispatch = COMPLEX_GROUP_GENERIC, behavior = PURE) -public abstract class Arg extends RBuiltinNode { +public abstract class Arg extends UnaryArithmeticBuiltinNode { + + public Arg() { + super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null); + } + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("z").mustBe(numericValue().or(complexValue()), RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION); + } + + @Override + public RType calculateResultType(RType argumentType) { + switch (argumentType) { + case Complex: + return RType.Double; + default: + return super.calculateResultType(argumentType); + } + } + + @Override + public int op(byte op) { + return 0; + } + + @Override + public int op(int op) { + return op; + } + + @Override + public double op(double op) { + if (op >= 0) { + return 0; + } else { + return Math.PI; + } + } + + @Override + public double opd(double re, double im) { + return Math.atan2(im, re); + } @Specialization - @TruffleBoundary - protected Object im(@SuppressWarnings("unused") Object value) { - throw RInternalError.unimplemented(); + @Override + public Object calculateUnboxed(Object op) { + return super.calculateUnboxed(op); } } 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 fbddf40edc89997b91ceba3ffd47500849c63733..12c5a5c6a3fd8aa93e02f1af5085dbdbdccad129 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 @@ -70,9 +70,8 @@ public abstract class Args extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); getNode = insert(GetNodeGen.create(null)); parentFrameNode = insert(ParentFrameNodeGen.create(null)); - } - return args((RFunction) getNode.execute(frame, funName, parentFrameNode.execute(frame, 1), RType.Function.getName(), true)); + return args((RFunction) getNode.execute(frame, funName.getDataAt(0), parentFrameNode.execute(frame, 1), RType.Function.getName(), true)); } @Specialization 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 3e159554532b967dda4eecd7b7db016bf5a478ea..a85f775ade321fc698918f2921d8f145e6e1452f 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 @@ -22,9 +22,15 @@ */ 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.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullConstant; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; 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.Specialization; import com.oracle.truffle.r.nodes.builtin.CastBuilder; @@ -41,6 +47,7 @@ import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RStringVector; +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.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; @@ -73,9 +80,18 @@ public abstract class Array extends RBuiltinNode { updateDimNames.executeRAbstractContainer(container, o); } + private String argType(Object arg) { + return ((RTypedValue) arg).getRType().getName(); + } + @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1); + Function<Object, Object> argType = this::argType; + casts.arg("data").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_VECTOR_BUT_WAS, "data", argType).mustNotBeNull().mustBe(abstractVectorValue()); + casts.arg("dim").defaultError(RError.SHOW_CALLER, RError.Message.CANNOT_BE_LENGTH, "dims", 0).mustNotBeNull().asIntegerVector().mustBe(notEmpty()); + casts.arg("dimnames").allowNull().shouldBe(instanceOf(RList.class), RError.SHOW_CALLER, + RError.Message.GENERIC, "non-list dimnames are disregarded; will be an error in R 3.3.0").mapIf( + instanceOf(RList.class).not(), nullConstant()); } private int dimDataHelper(RAbstractIntVector dim, int[] dimData) { 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 8d86ad3188d61287b99c0ff165393607945d8a24..446875d8fee0449ccf2df866acde5d3cd2edcc2c 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 @@ -43,6 +43,7 @@ import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RList; 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; @RBuiltin(name = "as.call", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) @@ -78,13 +79,15 @@ public abstract class AsCall extends RBuiltinNode { RLanguage l = (RLanguage) x.getDataAt(0); f = ((ReadVariableNode) RASTUtils.unwrap(l.getRep())).getIdentifier(); } - return Call.makeCallSourceUnavailable(f, makeNamesAndValues(x.getList())); + return Call.makeCallSourceUnavailable(f, makeNamesAndValues(x)); } - private RArgsValuesAndNames makeNamesAndValues(RList x) { + private RArgsValuesAndNames makeNamesAndValues(RAbstractContainer x) { int length = x.getLength() - 1; Object[] values = new Object[length]; - System.arraycopy(x.getDataWithoutCopying(), 1, values, 0, length); + for (int i = 0; i < length; i++) { + values[i] = x.getDataAtAsObject(i + 1); + } ArgumentsSignature signature; if (nullNamesProfile.profile(x.getNames(attrProfiles) == null)) { signature = ArgumentsSignature.empty(values.length); 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 472924e29227c82b5cd414f819e16e56996531c7..20b61c1e9c4bc222f8520b032360d290b780279b 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 @@ -22,107 +22,50 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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.CompilerDirectives; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.RDeparse; 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.RList; 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.RSymbol; -import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +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 { - @Child private CastStringNode castStringNode; + private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile(); - public abstract Object execute(Object obj); - - public static AsCharacter create() { - return AsCharacterNodeGen.create(null); - } - - private void initCast() { - if (castStringNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castStringNode = insert(CastStringNodeGen.create(false, false, false, false)); - } - } - - private String castString(int o) { - initCast(); - return (String) castStringNode.executeString(o); - } - - private String castString(double o) { - initCast(); - return (String) castStringNode.executeString(o); - } - - private String castString(byte o) { - initCast(); - return (String) castStringNode.executeString(o); - } - - private RStringVector castStringVector(Object o) { - initCast(); - return (RStringVector) ((RStringVector) castStringNode.executeString(o)).copyDropAttributes(); - } - - @Specialization - protected String doInt(int value) { - return castString(value); - } - - @Specialization - protected String doDouble(double value) { - return castString(value); - } - - @Specialization - protected String doLogical(byte value) { - return castString(value); - } - - @Specialization - protected String doRaw(RRaw value) { - initCast(); - return (String) castStringNode.executeString(value); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").allowNull().mapIf(instanceOf(RAbstractListVector.class).not(), asStringVector()); } @Specialization - protected String doString(String value) { - return value; + protected RAbstractStringVector asCharacter(@SuppressWarnings("unused") RNull n) { + return RDataFactory.createEmptyStringVector(); } @Specialization - protected String doSymbol(RSymbol value) { - return value.getName(); - } - - @Specialization - protected RStringVector doNull(@SuppressWarnings("unused") RNull value) { - return RDataFactory.createStringVector(0); - } - - @Specialization - protected RStringVector doStringVector(RStringVector vector) { - return RDataFactory.createStringVector(vector.getDataCopy(), vector.isComplete()); + protected RAbstractStringVector asCharacter(RAbstractStringVector v) { + if (noAttributes.profile(v.getAttributes() == null)) { + return v; + } else { + return (RAbstractStringVector) v.copyDropAttributes(); + } } @Specialization - protected RStringVector doList(RList list) { + protected RStringVector asCharacter(RAbstractListVector list) { int len = list.getLength(); boolean complete = RDataFactory.COMPLETE_VECTOR; String[] data = new String[len]; @@ -142,8 +85,4 @@ public abstract class AsCharacter extends RBuiltinNode { return RDataFactory.createStringVector(data, complete); } - @Specialization(guards = "!isRList(container)") - protected RStringVector doVector(RAbstractContainer container) { - return castStringVector(container); - } } 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 b962a7a88ae0cf3c00cd0ecced191c31f3bb5273..56de0ead0465957c4b675379c08bdefe7d3d360e 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 @@ -25,72 +25,37 @@ 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; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.unary.CastComplexNode; -import com.oracle.truffle.r.nodes.unary.CastComplexNodeGen; 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.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; @RBuiltin(name = "as.complex", kind = PRIMITIVE, parameterNames = {"x", "..."}, behavior = PURE) public abstract class AsComplex extends RBuiltinNode { - @Child private CastComplexNode castComplexNode; + private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile(); - private void initCast() { - if (castComplexNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castComplexNode = insert(CastComplexNodeGen.create(false, false, false)); - } - } - - @Specialization - protected RComplex doComplex(RComplex value) { - return value; - } - - @Specialization - protected RComplex doInt(int value) { - initCast(); - return (RComplex) castComplexNode.executeComplex(value); - } - - @Specialization - protected RComplex doDouble(double value) { - initCast(); - return (RComplex) castComplexNode.executeComplex(value); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").allowNull().asComplexVector(); } @Specialization - protected RComplex doLogical(byte value) { - initCast(); - return (RComplex) castComplexNode.executeComplex(value); + protected RAbstractComplexVector asComplex(@SuppressWarnings("unused") RNull n) { + return RDataFactory.createEmptyComplexVector(); } @Specialization - protected RComplex doString(String value) { - initCast(); - return (RComplex) castComplexNode.executeComplex(value); - } - - @Specialization - protected RComplexVector doNull(@SuppressWarnings("unused") RNull value) { - return RDataFactory.createComplexVector(0); - } - - @Specialization - protected RComplexVector doComplexVector(RComplexVector vector) { - return RDataFactory.createComplexVector(vector.getDataCopy(), vector.isComplete()); + protected RAbstractComplexVector asComplex(RAbstractComplexVector v) { + if (noAttributes.profile(v.getAttributes() == null)) { + return v; + } else { + return (RAbstractComplexVector) v.copyDropAttributes(); + } } - @Specialization - protected RComplexVector doIntVector(RAbstractVector vector) { - initCast(); - return (RComplexVector) castComplexNode.executeComplex(vector); - } } 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 d177ac1281fb04a3f54e792612a17b1cb20149d7..7f8d5c1015ee42e9828dca78e5eb8f24b4e877e8 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 @@ -25,84 +25,36 @@ 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; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.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.RDoubleSequence; -import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.RIntSequence; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +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 { - @Child private CastDoubleNode castDoubleNode; + private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile(); - private void initCast() { - if (castDoubleNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castDoubleNode = insert(CastDoubleNodeGen.create(false, false, false)); - } - } - - @Specialization - protected double asDouble(double value) { - return value; - } - - @Specialization - protected double asDoubleInt(int value) { - initCast(); - return (double) castDoubleNode.executeDouble(value); - } - - @Specialization - protected double asDouble(byte value) { - initCast(); - return (double) castDoubleNode.executeDouble(value); - } - - @Specialization - protected double asDouble(RComplex value) { - initCast(); - return (double) castDoubleNode.executeDouble(value); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").allowNull().asDoubleVector(); } @Specialization - protected double asDouble(String value) { - initCast(); - return (double) castDoubleNode.executeDouble(value); + protected RAbstractDoubleVector asDouble(@SuppressWarnings("unused") RNull n) { + return RDataFactory.createEmptyDoubleVector(); } @Specialization - protected RDoubleVector asDouble(@SuppressWarnings("unused") RNull vector) { - return RDataFactory.createDoubleVector(0); - } - - @Specialization - protected RDoubleVector asDouble(RDoubleVector vector) { - return RDataFactory.createDoubleVector(vector.getDataCopy(), vector.isComplete()); - } - - @Specialization - protected RDoubleSequence asDouble(RDoubleSequence sequence) { - return sequence; - } - - @Specialization - protected RDoubleSequence asDouble(RIntSequence sequence) { - return RDataFactory.createDoubleSequence(sequence.getStart(), sequence.getStride(), sequence.getLength()); - } - - @Specialization - protected RDoubleVector asDouble(RAbstractVector vector) { - initCast(); - return (RDoubleVector) castDoubleNode.executeDouble(vector); + protected RAbstractDoubleVector asDouble(RAbstractDoubleVector v) { + if (noAttributes.profile(v.getAttributes() == null)) { + return v; + } else { + return (RAbstractDoubleVector) v.copyDropAttributes(); + } } } 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 7afbe27d40577b1c9665fb2ad129a876f53815b4..721a2337534b85ac57bb4c89cdf22c1e64591786 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 @@ -22,19 +22,20 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.r.nodes.access.AccessArgumentNode; import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.WriteVariableNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.FormalArguments; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; @@ -46,15 +47,16 @@ 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.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RDataFactory; 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.RList; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; @@ -64,9 +66,18 @@ 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 { + + private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(RExpression.class)), RError.SHOW_CALLER2, RError.Message.TYPE_EXPECTED, RType.List.getName()); + casts.arg("envir").mustBe(instanceOf(REnvironment.class), RError.Message.INVALID_ENVIRONMENT); + } + @Specialization @TruffleBoundary - protected RFunction asFunction(RList x, REnvironment envir) { + 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"); } @@ -77,15 +88,15 @@ public abstract class AsFunction extends RBuiltinNode { saveArguments = SaveArgumentsNode.NO_ARGS; formals = FormalArguments.NO_ARGS; } else { - assert x.getNames() != null; - RStringVector names = x.getNames(); + assert x.getNames(attrProfiles) != null; + RStringVector names = x.getNames(attrProfiles); String[] argumentNames = new String[x.getLength() - 1]; RNode[] defaultValues = new RNode[x.getLength() - 1]; AccessArgumentNode[] argAccessNodes = new AccessArgumentNode[x.getLength() - 1]; RNode[] init = new RNode[x.getLength() - 1]; for (int i = 0; i < x.getLength() - 1; i++) { final RNode defaultValue; - Object arg = x.getDataAt(i); + Object arg = x.getDataAtAsObject(i); if (arg == RMissing.instance) { defaultValue = null; } else if (arg == RNull.instance) { @@ -121,9 +132,9 @@ public abstract class AsFunction extends RBuiltinNode { } RBaseNode body; - Object bodyObject = x.getDataAt(x.getLength() - 1); + Object bodyObject = x.getDataAtAsObject(x.getLength() - 1); if (bodyObject instanceof RLanguage) { - body = ((RLanguage) x.getDataAt(x.getLength() - 1)).getRep(); + body = ((RLanguage) x.getDataAtAsObject(x.getLength() - 1)).getRep(); } else if (bodyObject instanceof RSymbol) { body = ReadVariableNode.create(((RSymbol) bodyObject).getName()); } else { @@ -141,17 +152,4 @@ public abstract class AsFunction extends RBuiltinNode { RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); return RDataFactory.createFunction(RFunction.NO_NAME, callTarget, null, envir.getFrame()); } - - @Specialization - @TruffleBoundary - protected RFunction asFunction(RExpression x, REnvironment envir) { - return asFunction(x.getList(), envir); - } - - @SuppressWarnings("unused") - @Fallback - @TruffleBoundary - protected RFunction asFunction(Object x, Object envir) { - throw RError.error(this, RError.Message.TYPE_EXPECTED, RType.List.getName()); - } } 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 0f64433f130c212751add7f60c81ba9a70816ee7..77b77b31f14c03e1309d409685310217626fc0b5 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 @@ -25,92 +25,43 @@ 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; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.unary.CastIntegerNode; -import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.conn.RConnection; -import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RDataFactory; -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.RRaw; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "as.integer", kind = PRIMITIVE, parameterNames = {"x", "..."}, behavior = PURE) public abstract class AsInteger extends RBuiltinNode { - @Child private CastIntegerNode castIntNode; + private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile(); - private void initCast() { - if (castIntNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castIntNode = insert(CastIntegerNodeGen.create(false, false, false)); - } - } - - @Specialization - protected int asInteger(int value) { - return value; - } - - @Specialization - protected int asInteger(double value) { - initCast(); - return (int) castIntNode.executeInt(value); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").allowNull().asIntegerVector(); } @Specialization - protected int asInteger(byte value) { - initCast(); - return (int) castIntNode.executeInt(value); - } - - @Specialization - protected int asInteger(RComplex value) { - initCast(); - return (int) castIntNode.executeInt(value); - } - - @Specialization - protected int asInteger(RRaw value) { - initCast(); - return (int) castIntNode.executeInt(value); - } - - @Specialization - protected int asInteger(String value) { - initCast(); - return (int) castIntNode.executeInt(value); - } - - @Specialization - protected RIntVector asInteger(@SuppressWarnings("unused") RNull value) { + protected RAbstractIntVector asInteger(@SuppressWarnings("unused") RNull n) { return RDataFactory.createEmptyIntVector(); } @Specialization - protected RIntVector asInteger(RIntVector vector) { - return RDataFactory.createIntVector(vector.getDataCopy(), vector.isComplete()); - } - - @Specialization - protected RIntVector asInteger(RIntSequence sequence) { - return (RIntVector) sequence.createVector(); - } - - @Specialization - protected RAbstractIntVector asInteger(RAbstractVector vector) { - initCast(); - return (RAbstractIntVector) castIntNode.executeInt(vector); + protected RAbstractIntVector asInteger(RAbstractIntVector v) { + if (noAttributes.profile(v.getAttributes() == null)) { + return v; + } else { + return (RAbstractIntVector) v.copyDropAttributes(); + } } @Specialization protected int asInteger(RConnection conn) { return conn.getDescriptor(); } + } 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 640ce0cc091da04dbb221a7b92356d03ed43c468..fbdc14690c61b46e14d132bc7a489abfbd9c28a9 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 @@ -25,76 +25,36 @@ 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; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.unary.CastLogicalNode; -import com.oracle.truffle.r.nodes.unary.CastLogicalNodeGen; 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.RLogicalVector; 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.RAbstractLogicalVector; @RBuiltin(name = "as.logical", kind = PRIMITIVE, parameterNames = {"x", "..."}, behavior = PURE) public abstract class AsLogical extends RBuiltinNode { - @Child private CastLogicalNode castLogicalNode; + private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile(); - private byte castLogical(Object o) { - if (castLogicalNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castLogicalNode = insert(CastLogicalNodeGen.create(false, false, false)); - } - return (byte) castLogicalNode.execute(o); - } - - private RLogicalVector castLogicalVector(Object o) { - if (castLogicalNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castLogicalNode = insert(CastLogicalNodeGen.create(false, false, false)); - } - return (RLogicalVector) castLogicalNode.execute(o); - } - - @Specialization - protected byte asLogical(byte value) { - return value; - } - - @Specialization - protected byte asLogical(int value) { - return castLogical(value); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").allowNull().asLogicalVector(); } @Specialization - protected byte asLogical(double value) { - return castLogical(value); + protected RAbstractLogicalVector asLogicaleger(@SuppressWarnings("unused") RNull n) { + return RDataFactory.createEmptyLogicalVector(); } @Specialization - protected byte asLogical(RComplex value) { - return castLogical(value); - } - - @Specialization - protected byte asLogical(String value) { - return castLogical(value); - } - - @Specialization - protected RLogicalVector asLogical(@SuppressWarnings("unused") RNull vector) { - return RDataFactory.createLogicalVector(0); - } - - @Specialization - protected RLogicalVector asLogical(RLogicalVector vector) { - return RDataFactory.createLogicalVector(vector.getDataCopy(), vector.isComplete()); - } - - @Specialization - protected RLogicalVector asLogical(RAbstractContainer container) { - return castLogicalVector(container); + protected RAbstractLogicalVector asLogicaleger(RAbstractLogicalVector v) { + if (noAttributes.profile(v.getAttributes() == null)) { + return v; + } else { + return (RAbstractLogicalVector) v.copyDropAttributes(); + } } } 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 4d03ae68c19173386b5d5fe3bd0fc8f2c07f16f0..dafd3a6f8a5ecd8de9ec560f43221edabc0d4b49 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 @@ -25,93 +25,36 @@ 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; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.unary.CastIntegerNode; -import com.oracle.truffle.r.nodes.unary.CastRawNode; -import com.oracle.truffle.r.nodes.unary.CastRawNodeGen; 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.RList; 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.model.RAbstractVector; +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 { - @Child private CastIntegerNode castInteger; - @Child private CastRawNode castRawNode; + private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile(); - private void initCast() { - if (castRawNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castRawNode = insert(CastRawNodeGen.create(false, false, false)); - } - } - - @Specialization - protected RRawVector asRaw(@SuppressWarnings("unused") RNull vector) { - return RDataFactory.createRawVector(0); - } - - @Specialization - protected RRaw asRaw(byte logical) { - initCast(); - return (RRaw) castRawNode.executeRaw(logical); - } - - @Specialization - protected RRaw asRaw(int value) { - initCast(); - return (RRaw) castRawNode.executeRaw(value); - } - - @Specialization - protected RRaw asRaw(double value) { - initCast(); - return (RRaw) castRawNode.executeRaw(value); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").allowNull().asRawVector(); } @Specialization - protected RRaw asRaw(RComplex value) { - initCast(); - return (RRaw) castRawNode.executeRaw(value); + protected RAbstractRawVector asRaw(@SuppressWarnings("unused") RNull n) { + return RDataFactory.createEmptyRawVector(); } @Specialization - protected RRaw asRaw(String value) { - initCast(); - return (RRaw) castRawNode.executeRaw(value); - } - - @Specialization - protected RRaw asRaw(RRaw value) { - return value; - } - - @Specialization - protected RRawVector asRaw(RRawVector value) { - return RDataFactory.createRawVector(value.getDataCopy()); - } - - @Specialization - protected RRawVector asRaw(RList value) { - initCast(); - int length = value.getLength(); - RRawVector result = RDataFactory.createRawVector(length); - for (int i = 0; i < length; i++) { - result.updateDataAt(i, (RRaw) castRawNode.executeRaw(value.getDataAt(i))); + protected RAbstractRawVector asRaw(RAbstractRawVector v) { + if (noAttributes.profile(v.getAttributes() == null)) { + return v; + } else { + return (RAbstractRawVector) v.copyDropAttributes(); } - return result; - } - - @Specialization - protected RRawVector asRaw(RAbstractVector vector) { - initCast(); - return (RRawVector) castRawNode.executeRaw(vector); } } 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 e651355cac72294ece64a866aab8351da1d9bfcc..e9c48b7c3cea92ec62c25523f801ef17ef5ca8bd 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 @@ -22,7 +22,8 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; +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.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -31,13 +32,14 @@ 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.Node; +import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.function.ClassHierarchyNode; import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode; @@ -46,30 +48,27 @@ import com.oracle.truffle.r.nodes.unary.CastComplexNode; import com.oracle.truffle.r.nodes.unary.CastDoubleNode; import com.oracle.truffle.r.nodes.unary.CastExpressionNode; import com.oracle.truffle.r.nodes.unary.CastIntegerNode; -import com.oracle.truffle.r.nodes.unary.CastListNode; import com.oracle.truffle.r.nodes.unary.CastListNodeGen; 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.CastStringNode; import com.oracle.truffle.r.nodes.unary.CastSymbolNode; 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.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.RAttributeProfiles; -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.RExpression; import com.oracle.truffle.r.runtime.data.RLanguage; -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.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.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "as.vector", kind = INTERNAL, parameterNames = {"x", "mode"}, behavior = COMPLEX) @@ -83,7 +82,7 @@ public abstract class AsVector extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.arg("mode").mustBe(scalarStringValue(), RError.Message.INVALID_ARGUMENT, "mode"); + casts.arg("mode").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst(); } protected static AsVectorInternal createInternal() { @@ -111,184 +110,121 @@ public abstract class AsVector extends RBuiltinNode { return internal.execute(x, mode); } - @TypeSystemReference(RTypes.class) public abstract static class AsVectorInternal extends Node { public abstract Object execute(Object x, String mode); - private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); - - @Specialization(guards = "castToString(mode)") - protected Object asVectorString(Object x, @SuppressWarnings("unused") String mode, // - @Cached("create()") AsCharacter asCharacter) { - return asCharacter.execute(x); - } - - @Specialization(guards = "castToInt(x, mode)") - protected Object asVectorInt(RAbstractContainer x, @SuppressWarnings("unused") String mode, // - @Cached("createNonPreserving()") CastIntegerNode cast) { - return cast.execute(x); - } - - @Specialization(guards = "castToDouble(x, mode)") - protected Object asVectorDouble(RAbstractContainer x, @SuppressWarnings("unused") String mode, // - @Cached("createNonPreserving()") CastDoubleNode cast) { - return cast.execute(x); - } - - @Specialization(guards = "castToComplex(x, mode)") - protected Object asVectorComplex(RAbstractContainer x, @SuppressWarnings("unused") String mode, // - @Cached("createNonPreserving()") CastComplexNode cast) { - return cast.execute(x); - } - - @Specialization(guards = "castToLogical(x, mode)") - protected Object asVectorLogical(RAbstractContainer x, @SuppressWarnings("unused") String mode, // - @Cached("createNonPreserving()") CastLogicalNode cast) { - return cast.execute(x); - } - - @Specialization(guards = "castToRaw(x, mode)") - protected Object asVectorRaw(RAbstractContainer x, @SuppressWarnings("unused") String mode, // - @Cached("createNonPreserving()") CastRawNode cast) { - return cast.execute(x); - } - - protected static CastListNode createListCast() { - return CastListNodeGen.create(true, false, false); - } - - @Specialization(guards = "castToList(mode)") - protected Object asVectorList(RAbstractContainer x, @SuppressWarnings("unused") String mode, // - @Cached("createListCast()") CastListNode cast) { - return cast.execute(x); - } - - @Specialization(guards = "castToSymbol(x, mode)") - protected Object asVectorSymbol(RAbstractContainer x, @SuppressWarnings("unused") String mode, // - @Cached("createNonPreserving()") CastSymbolNode cast) { - return cast.execute(x); - } - - @Specialization(guards = "castToExpression(mode)") - protected Object asVectorExpression(Object x, @SuppressWarnings("unused") String mode, // - @Cached("createNonPreserving()") CastExpressionNode cast) { - return cast.execute(x); - } - - @Specialization(guards = "castToList(mode)") - protected RAbstractVector asVectorList(@SuppressWarnings("unused") RNull x, @SuppressWarnings("unused") String mode) { - return RDataFactory.createList(); - } - - @Specialization(guards = "isSymbol(x, mode)") - protected RSymbol asVectorSymbol(RSymbol x, @SuppressWarnings("unused") String mode) { - String sName = x.getName(); - return RDataFactory.createSymbol(sName); - } - - protected boolean isSymbol(@SuppressWarnings("unused") RSymbol x, String mode) { - return RType.Symbol.getName().equals(mode); - } - - @Specialization(guards = "modeIsAny(mode)") - protected RAbstractVector asVector(RList x, @SuppressWarnings("unused") String mode) { - RList result = x.copyWithNewDimensions(null); - result.copyNamesFrom(attrProfiles, x); - return result; - } - - @Specialization(guards = "modeIsAny(mode)") - protected RLanguage asVector(RLanguage x, @SuppressWarnings("unused") String mode) { - return x.copy(); - } - - @Specialization(guards = "modeIsAny(mode)") - protected RNull asVector(RNull x, @SuppressWarnings("unused") String mode) { - return x; - } - - @Specialization(guards = "modeIsPairList(mode)") - @TruffleBoundary - protected Object asVectorPairList(RList x, @SuppressWarnings("unused") String mode) { - // TODO implement non-empty element list conversion; this is a placeholder for type test - if (x.getLength() == 0) { - return RNull.instance; - } else { - Object list = RNull.instance; - RStringVector names = x.getNames(); - for (int i = x.getLength() - 1; i >= 0; i--) { - Object name = names == null ? RNull.instance : RDataFactory.createSymbolInterned(names.getDataAt(i)); - Object data = x.getDataAt(i); - list = RDataFactory.createPairList(data, list, name); + 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 list; } + return res; + } + + protected static CastNode createCast(RType type) { + if (type != null) { + switch (type) { + case Any: + return null; + case Character: + return CastStringNode.createNonPreserving(); + case Complex: + return CastComplexNode.createNonPreserving(); + case Double: + return CastDoubleNode.createNonPreserving(); + case Expression: + return CastExpressionNode.createNonPreserving(); + case Function: + throw RInternalError.unimplemented("as.vector cast to 'function'"); + case Integer: + return CastIntegerNode.createNonPreserving(); + case List: + return CastListNodeGen.create(true, false, false); + case Logical: + return CastLogicalNode.createNonPreserving(); + case PairList: + return CastPairListNodeGen.create(); + case Raw: + return CastRawNode.createNonPreserving(); + case Symbol: + return CastSymbolNode.createNonPreserving(); + } + } + throw RError.error(RError.SHOW_CALLER, Message.INVALID_ARGUMENT, "mode"); } - @Specialization(guards = "modeIsAny(mode)") - protected RAbstractVector asVectorAny(RAbstractVector x, @SuppressWarnings("unused") String mode) { - return x.copyWithNewDimensions(null); - } - - @Specialization(guards = "modeMatches(x, mode)") - protected RAbstractVector asVector(RAbstractVector x, @SuppressWarnings("unused") String mode) { - return x.copyWithNewDimensions(null); - } - - protected boolean castToInt(RAbstractContainer x, String mode) { - return x.getElementClass() != RInteger.class && RType.Integer.getName().equals(mode); - } - - protected boolean castToDouble(RAbstractContainer x, String mode) { - return x.getElementClass() != RDouble.class && (RType.Double.getClazz().equals(mode) || RType.Double.getName().equals(mode)); - } - - protected boolean castToComplex(RAbstractContainer x, String mode) { - return x.getElementClass() != RComplex.class && RType.Complex.getName().equals(mode); - } - - protected boolean castToLogical(RAbstractContainer x, String mode) { - return x.getElementClass() != RLogical.class && RType.Logical.getName().equals(mode); - } - - protected boolean castToString(String mode) { - return RType.Character.getName().equals(mode); - } - - protected boolean castToRaw(RAbstractContainer x, String mode) { - return x.getElementClass() != RRaw.class && RType.Raw.getName().equals(mode); - } - - protected boolean castToList(String mode) { - return RType.List.getName().equals(mode); - } - - protected boolean castToSymbol(RAbstractContainer x, String mode) { - return x.getElementClass() != Object.class && RType.Symbol.getName().equals(mode); - } - - protected boolean castToExpression(String mode) { - return RType.Expression.getName().equals(mode); - } - - protected boolean modeMatches(RAbstractVector x, String mode) { - return RRuntime.classToString(x.getElementClass()).equals(mode) || x.getElementClass() == RDouble.class && RType.Double.getName().equals(mode); - } - - protected boolean modeIsAny(String mode) { - return RType.Any.getName().equals(mode); - } - - protected boolean modeIsPairList(String mode) { - return RType.PairList.getName().equals(mode); + protected boolean matchesMode(String mode, String cachedMode) { + return mode == cachedMode || indirectMatchProfile.profile(cachedMode.equals(mode)); } + // there should never be more than ~12 specializations @SuppressWarnings("unused") - @Fallback - @TruffleBoundary - protected RAbstractVector asVectorWrongMode(Object x, String mode) { - throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "mode"); + @Specialization(limit = "99", guards = "matchesMode(mode, cachedMode)") + 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)); + } + + protected abstract static class CastPairListNode extends CastNode { + + private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + + @Specialization + @TruffleBoundary + protected Object castPairlist(RAbstractListVector x) { + // TODO implement non-empty element list conversion; this is a placeholder for type + // test + if (x.getLength() == 0) { + return RNull.instance; + } else { + Object list = RNull.instance; + RStringVector names = x.getNames(attrProfiles); + for (int i = x.getLength() - 1; i >= 0; i--) { + Object name = names == null ? RNull.instance : RDataFactory.createSymbolInterned(names.getDataAt(i)); + Object data = x.getDataAt(i); + list = RDataFactory.createPairList(data, list, name); + } + return list; + } + } + + @Fallback + protected Object castPairlist(@SuppressWarnings("unused") Object x) { + throw RInternalError.unimplemented("non-list casts to pairlist"); + } } } } 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 f0db2b54703a95e4e9f0ed6e19fd5af7cbd31acb..9bf1e7f47e64ea1b3cedd2c1c98a218beeb572b1 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 @@ -22,7 +22,6 @@ */ 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.singleElement; import static com.oracle.truffle.r.runtime.RVisibility.OFF; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; @@ -39,9 +38,10 @@ 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.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.REnvironment.PutException; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** * The {@code assign} builtin. There are two special cases worth optimizing: @@ -56,32 +56,28 @@ import com.oracle.truffle.r.runtime.env.REnvironment.PutException; @RBuiltin(name = "assign", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "value", "envir", "inherits"}, behavior = COMPLEX) public abstract class Assign extends RBuiltinNode { + public abstract Object execute(String x, Object value, REnvironment envir, byte inherits); + private final BranchProfile errorProfile = BranchProfile.create(); - private final BranchProfile warningProfile = BranchProfile.create(); + private final boolean direct; - /** - * TODO: This method becomes obsolete when Assign and AssignFastPaths are modified to have the - * (String, Object, REnvironment, boolean) signature. - */ - private String checkVariable(RAbstractStringVector xVec) { - int len = xVec.getLength(); - if (len == 1) { - return xVec.getDataAt(0); - } else if (len == 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_FIRST_ARGUMENT); - } else { - warningProfile.enter(); - RError.warning(this, RError.Message.ONLY_FIRST_VARIABLE_NAME); - return xVec.getDataAt(0); - } + protected Assign() { + this(false); + } + + protected Assign(boolean direct) { + this.direct = direct; + } + + private RBaseNode errorContext() { + return direct ? this : RError.SHOW_CALLER; } @Override protected void createCasts(CastBuilder casts) { casts.arg("x").asStringVector().shouldBe(singleElement(), RError.Message.ONLY_FIRST_VARIABLE_NAME).findFirst(RError.Message.INVALID_FIRST_ARGUMENT); - casts.arg("envir").mustBe(nullValue().not(), RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(REnvironment.class, RError.Message.INVALID_ARGUMENT, "envir"); + casts.arg("envir").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(REnvironment.class, RError.Message.INVALID_ARGUMENT, "envir"); // this argument could be made Boolean unless there were AssignFastPath relying upon the // byte argument @@ -92,9 +88,10 @@ public abstract class Assign extends RBuiltinNode { * The general case that requires searching the environment hierarchy. */ @Specialization - protected Object assignInherit(RAbstractStringVector xVec, Object value, REnvironment envir, byte inherits, // - @Cached("createBinaryProfile()") ConditionProfile inheritsProfile) { - String x = checkVariable(xVec); + protected Object assign(String x, Object value, REnvironment envir, byte inherits, // + @Cached("createBinaryProfile()") ConditionProfile inheritsProfile, + @Cached("createBinaryProfile()") ConditionProfile isShareableProfile, + @Cached("createBinaryProfile()") ConditionProfile isRefCountUpdateable) { REnvironment env = envir; if (inheritsProfile.profile(RRuntime.fromLogical(inherits))) { while (env != REnvironment.emptyEnv()) { @@ -112,15 +109,22 @@ public abstract class Assign extends RBuiltinNode { } if (env == REnvironment.emptyEnv()) { errorProfile.enter(); - throw RError.error(this, RError.Message.CANNOT_ASSIGN_IN_EMPTY_ENV); + throw RError.error(errorContext(), RError.Message.CANNOT_ASSIGN_IN_EMPTY_ENV); + } + } + if (isShareableProfile.profile(value instanceof RShareable)) { + RShareable shareable = (RShareable) value; + if (isRefCountUpdateable.profile(!shareable.isSharedPermanent())) { + shareable.incRefCount(); } } try { env.put(x, value); } catch (PutException ex) { errorProfile.enter(); - throw RError.error(this, ex); + throw RError.error(errorContext(), 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 2b02daeba067b2adcd8bd163961271a7858f2e46..7aa2a9e377a79c7ff78ff600516a84f1fafb6a78 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 @@ -22,23 +22,26 @@ */ 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.numericValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; 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.INTERNAL; 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.CastBuilder; 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.RAttributeProfiles; 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.RAbstractIntVector; +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.env.REnvironment.DetachException; @@ -51,7 +54,9 @@ public class AttachFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1); + casts.arg("what").allowNull().mustBe(instanceOf(REnvironment.class).or(instanceOf(RAbstractListVector.class)), RError.Message.ATTACH_BAD_TYPE); + casts.arg("pos").mustBe(numericValue(), Message.MUST_BE_INTEGER, "pos").asIntegerVector(); + casts.arg("name").mustBe(stringValue()); } @Specialization @@ -70,7 +75,7 @@ public class AttachFunctions { for (int i = 0; i < names.getLength(); i++) { String key = names.getDataAt(i); Object value = what.get(key); - // TODO copy? + // TODO: copy/sharing? env.safePut(key, value); } doAttachEnv(pos.getDataAt(0), env); @@ -79,22 +84,17 @@ public class AttachFunctions { @Specialization @TruffleBoundary - protected REnvironment doAttach(RList what, RAbstractIntVector pos, RAbstractStringVector name) { + protected REnvironment doAttach(RAbstractListVector what, RAbstractIntVector pos, RAbstractStringVector name) { REnvironment env = RDataFactory.createNewEnv(name.getDataAt(0)); RStringVector names = what.getNames(attrProfiles); for (int i = 0; i < names.getLength(); i++) { + // TODO: copy/sharing? env.safePut(names.getDataAt(i), what.getDataAt(i)); } doAttachEnv(pos.getDataAt(0), env); return env; } - @SuppressWarnings("unused") - @Fallback - protected REnvironment doAttach(Object what, Object pos, Object name) { - throw RError.error(this, RError.Message.ATTACH_BAD_TYPE); - } - private static void doAttachEnv(int pos, REnvironment env) { // GnuR appears to allow any value of pos except 1. // Values < 1 are interpreted as 2 @@ -111,7 +111,7 @@ public class AttachFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(0); + casts.arg("pos").mustBe(numericValue(), Message.MUST_BE_INTEGER, "pos").asIntegerVector(); } @Specialization 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 ff4f6c27ec13c932a6ed6dd1d7b6462a1ee6054a..de77e82951784c475c68e5dae88a2091751d7e31 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 @@ -22,6 +22,9 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +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.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -32,9 +35,12 @@ 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.nodes.builtin.CastBuilder; 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; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; @@ -42,8 +48,8 @@ import com.oracle.truffle.r.runtime.data.RAttributes; import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; 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.RStringVector; 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; @@ -52,16 +58,29 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; public abstract class Attr extends RBuiltinNode { private final ConditionProfile searchPartialProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile errorProfile = BranchProfile.create(); private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + private final BranchProfile errorProfile = BranchProfile.create(); @CompilationFinal private String cachedName = ""; @CompilationFinal private String cachedInternedName = ""; + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{RMissing.instance, RMissing.instance, RRuntime.asLogical(false)}; + } + + @Override + protected void createCasts(CastBuilder casts) { + // Note: checking RAttributable.class does not work for scalars + // casts.arg("x").mustBe(RAttributable.class, Message.UNIMPLEMENTED_ARGUMENT_TYPE); + casts.arg("which").mustBe(stringValue(), Message.MUST_BE_CHARACTER, "which").asStringVector().mustBe(singleElement(), RError.Message.EXACTLY_ONE_WHICH).findFirst(); + casts.arg("exact").asLogicalVector().findFirst().map(toBoolean()); + } + private String intern(String name) { if (cachedName == null) { // unoptimized case - return name.intern(); + return Utils.intern(name); } if (cachedName == name) { // cached case @@ -72,12 +91,12 @@ public abstract class Attr extends RBuiltinNode { if (cachedName == "") { // Checkstyle: resume StringLiteralEquality cachedName = name; - cachedInternedName = name.intern(); + cachedInternedName = Utils.intern(name); } else { cachedName = null; cachedInternedName = null; } - return name.intern(); + return Utils.intern(name); } private static Object searchKeyPartial(RAttributes attributes, String name) { @@ -95,41 +114,32 @@ public abstract class Attr extends RBuiltinNode { return val; } - private Object attrRA(RAttributable attributable, String name) { + private Object attrRA(RAttributable attributable, String name, boolean exact) { RAttributes attributes = attributable.getAttributes(); if (attributes == null) { return RNull.instance; } else { Object result = attributes.get(name); - if (searchPartialProfile.profile(result == null)) { + if (searchPartialProfile.profile(!exact && result == null)) { return searchKeyPartial(attributes, name); } - return result; + return result == null ? RNull.instance : result; } } @Specialization - protected RNull attr(RNull container, @SuppressWarnings("unused") String name) { + protected RNull attr(RNull container, @SuppressWarnings("unused") String name, @SuppressWarnings("unused") boolean exact) { return container; } @Specialization(guards = "!isRowNamesAttr(name)") - protected Object attr(RAbstractContainer container, String name) { - return attrRA(container, intern(name)); - } - - public static Object getFullRowNames(Object a) { - 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; - } + protected Object attr(RAbstractContainer container, String name, boolean exact) { + return attrRA(container, intern(name), exact); } @Specialization(guards = "isRowNamesAttr(name)") - protected Object attrRowNames(RAbstractContainer container, @SuppressWarnings("unused") String name) { + protected Object attrRowNames(RAbstractContainer container, @SuppressWarnings("unused") String name, @SuppressWarnings("unused") boolean exact) { + // TODO: if exact == false, check for partial match (there is an ignored tests for it) RAttributes attributes = container.getAttributes(); if (attributes == null) { return RNull.instance; @@ -138,49 +148,31 @@ public abstract class Attr extends RBuiltinNode { } } - @Specialization(guards = {"exactlyOne(name)", "isRowNamesAttr(name)"}) - protected Object attrRowNames(RAbstractContainer container, RStringVector name) { - return attrRowNames(container, name.getDataAt(0)); - } - - @Specialization(guards = {"exactlyOne(name)", "!isRowNamesAttr(name)"}) - protected Object attr(RAbstractContainer container, RStringVector name) { - return attr(container, name.getDataAt(0)); - } - - @SuppressWarnings("unused") - @Specialization(guards = "!exactlyOne(name)") - protected Object attrEmtpyName(RAbstractContainer container, RStringVector name) { - throw RError.error(this, RError.Message.EXACTLY_ONE_WHICH); - } - /** * All other, non-performance centric, {@link RAttributable} types. */ @Fallback @TruffleBoundary - protected Object attr(Object object, Object name) { - String sname = RRuntime.asString(name); - if (sname == null) { - throw RError.error(this, RError.Message.MUST_BE_CHARACTER, "which"); - } + protected Object attr(Object object, Object name, Object exact) { if (object instanceof RAttributable) { - return attrRA((RAttributable) object, intern(sname)); + return attrRA((RAttributable) object, intern((String) name), (boolean) exact); } else { errorProfile.enter(); throw RError.nyi(this, "object cannot be attributed"); } } - protected static boolean isRowNamesAttr(String name) { - return name.equals(RRuntime.ROWNAMES_ATTR_KEY); - } - - protected static boolean isRowNamesAttr(RStringVector name) { - return isRowNamesAttr(name.getDataAt(0)); + public static Object getFullRowNames(Object a) { + 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; + } } - protected static boolean exactlyOne(RStringVector name) { - return name.getLength() == 1; + protected static boolean isRowNamesAttr(String name) { + return name.equals(RRuntime.ROWNAMES_ATTR_KEY); } } 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 9c39c508526239c6362bd5a201b28acca420f4e5..effc12dc4a140b4275b8d7822ef084206ac59b97 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 @@ -19,6 +19,8 @@ import static com.oracle.truffle.r.library.stats.StatsUtil.DBL_MIN_EXP; import static com.oracle.truffle.r.library.stats.StatsUtil.M_LOG10_2; import static com.oracle.truffle.r.library.stats.StatsUtil.M_PI; import static com.oracle.truffle.r.library.stats.StatsUtil.fmax2; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; 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; @@ -26,11 +28,11 @@ 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.Fallback; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.NodeChildren; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.library.stats.GammaFunctions; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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; @@ -39,7 +41,6 @@ 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.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; @@ -71,6 +72,11 @@ public class BaseGammaFunctions { private final NACheck naValCheck = NACheck.create(); + @Override + protected void createCasts(CastBuilder 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); @@ -93,17 +99,6 @@ public class BaseGammaFunctions { return lgamma(RClosures.createLogicalToDoubleVector(x)); } - @Specialization - @TruffleBoundary - protected Object lgamma(@SuppressWarnings("unused") RAbstractComplexVector x) { - return RError.error(this, RError.Message.UNIMPLEMENTED_COMPLEX_FUN); - } - - @Fallback - @TruffleBoundary - protected Object lgamma(@SuppressWarnings("unused") Object x) { - throw RError.error(this, RError.Message.NON_NUMERIC_MATH); - } } @RBuiltin(name = "digamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) @@ -121,6 +116,11 @@ public class BaseGammaFunctions { return dpsiFnCalc.executeDouble(x, n, kode, ans); } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue()).asDoubleVector(); + } + @Specialization protected RDoubleVector digamma(RAbstractDoubleVector x) { naValCheck.enable(x); @@ -156,17 +156,6 @@ public class BaseGammaFunctions { return digamma(RClosures.createLogicalToDoubleVector(x)); } - @Specialization - @TruffleBoundary - protected Object digamma(@SuppressWarnings("unused") RAbstractComplexVector x) { - return RError.error(this, RError.Message.UNIMPLEMENTED_COMPLEX_FUN); - } - - @Fallback - @TruffleBoundary - protected Object digamma(@SuppressWarnings("unused") Object x) { - throw RError.error(this, RError.Message.NON_NUMERIC_MATH); - } } @NodeChildren({@NodeChild(value = "x"), @NodeChild(value = "n"), @NodeChild(value = "kode"), @NodeChild(value = "ans")}) 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 1b9d8c311222962e25d0bd5c7565c90cf4ea1b92..eb4c0c8d666dbf715221aff9e38e4fc14bce682c 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 @@ -22,14 +22,16 @@ */ 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.nodes.RRootNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.binary.BinaryArithmeticNodeGen; +import com.oracle.truffle.r.nodes.binary.BinaryArithmeticSpecial; import com.oracle.truffle.r.nodes.binary.BinaryBooleanNodeGen; import com.oracle.truffle.r.nodes.binary.BinaryBooleanScalarNodeGen; -import com.oracle.truffle.r.nodes.binary.ColonNode; -import com.oracle.truffle.r.nodes.binary.ColonNodeGen; +import com.oracle.truffle.r.nodes.binary.BinaryBooleanSpecial; import com.oracle.truffle.r.nodes.builtin.RBuiltinPackage; import com.oracle.truffle.r.nodes.builtin.base.fastpaths.AssignFastPathNodeGen; import com.oracle.truffle.r.nodes.builtin.base.fastpaths.ExistsFastPathNodeGen; @@ -44,12 +46,50 @@ import com.oracle.truffle.r.nodes.builtin.base.foreign.DotC; import com.oracle.truffle.r.nodes.builtin.base.foreign.DotCNodeGen; import com.oracle.truffle.r.nodes.builtin.base.foreign.ForeignFunctions; import com.oracle.truffle.r.nodes.builtin.base.foreign.ForeignFunctionsFactory; +import com.oracle.truffle.r.nodes.builtin.base.infix.AccessField; +import com.oracle.truffle.r.nodes.builtin.base.infix.AccessFieldNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.AssignBuiltin; +import com.oracle.truffle.r.nodes.builtin.base.infix.AssignBuiltinEq; +import com.oracle.truffle.r.nodes.builtin.base.infix.AssignBuiltinEqNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.AssignBuiltinNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.AssignOuterBuiltin; +import com.oracle.truffle.r.nodes.builtin.base.infix.AssignOuterBuiltinNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.BraceBuiltin; +import com.oracle.truffle.r.nodes.builtin.base.infix.BraceBuiltinNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.BreakBuiltin; +import com.oracle.truffle.r.nodes.builtin.base.infix.BreakBuiltinNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.ForBuiltin; +import com.oracle.truffle.r.nodes.builtin.base.infix.ForBuiltinNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.FunctionBuiltin; +import com.oracle.truffle.r.nodes.builtin.base.infix.FunctionBuiltinNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.IfBuiltin; +import com.oracle.truffle.r.nodes.builtin.base.infix.IfBuiltinNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.NextBuiltin; +import com.oracle.truffle.r.nodes.builtin.base.infix.NextBuiltinNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.ParenBuiltin; +import com.oracle.truffle.r.nodes.builtin.base.infix.ParenBuiltinNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.RepeatBuiltin; +import com.oracle.truffle.r.nodes.builtin.base.infix.RepeatBuiltinNodeGen; +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.builtin.base.infix.Subset; +import com.oracle.truffle.r.nodes.builtin.base.infix.SubsetNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.Tilde; +import com.oracle.truffle.r.nodes.builtin.base.infix.TildeNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.UpdateField; +import com.oracle.truffle.r.nodes.builtin.base.infix.UpdateFieldNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.UpdateSubscript; +import com.oracle.truffle.r.nodes.builtin.base.infix.UpdateSubscriptNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.UpdateSubset; +import com.oracle.truffle.r.nodes.builtin.base.infix.UpdateSubsetNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.WhileBuiltin; +import com.oracle.truffle.r.nodes.builtin.base.infix.WhileBuiltinNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.system.SystemFunction; +import com.oracle.truffle.r.nodes.builtin.base.system.SystemFunctionNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRContext; import com.oracle.truffle.r.nodes.builtin.fastr.FastRContextFactory; import com.oracle.truffle.r.nodes.builtin.fastr.FastRDebug; import com.oracle.truffle.r.nodes.builtin.fastr.FastRDebugNodeGen; -import com.oracle.truffle.r.nodes.builtin.fastr.FastRFunctionProfiler; -import com.oracle.truffle.r.nodes.builtin.fastr.FastRFunctionProfilerFactory; import com.oracle.truffle.r.nodes.builtin.fastr.FastRIdentity; import com.oracle.truffle.r.nodes.builtin.fastr.FastRIdentityNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRInspect; @@ -60,6 +100,10 @@ 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.FastRStackTrace; import com.oracle.truffle.r.nodes.builtin.fastr.FastRStackTraceNodeGen; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRStats.FastRProfAttr; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRStats.FastRProfFuncounts; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRStats.FastRProfTypecounts; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRStatsFactory; import com.oracle.truffle.r.nodes.builtin.fastr.FastRSyntaxTree; import com.oracle.truffle.r.nodes.builtin.fastr.FastRSyntaxTreeNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRThrowIt; @@ -74,14 +118,18 @@ import com.oracle.truffle.r.nodes.builtin.fastr.FastrDqrls; import com.oracle.truffle.r.nodes.builtin.fastr.FastrDqrlsNodeGen; import com.oracle.truffle.r.nodes.unary.UnaryNotNode; import com.oracle.truffle.r.nodes.unary.UnaryNotNodeGen; +import com.oracle.truffle.r.runtime.RVisibility; import com.oracle.truffle.r.runtime.builtins.FastPathFactory; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.nodes.RFastPathNode; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; +import com.oracle.truffle.r.runtime.ops.BinaryArithmeticFactory; import com.oracle.truffle.r.runtime.ops.BinaryCompare; import com.oracle.truffle.r.runtime.ops.BinaryLogic; +import com.oracle.truffle.r.runtime.ops.BooleanOperationFactory; import com.oracle.truffle.r.runtime.ops.UnaryArithmetic; +import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory; public class BasePackage extends RBuiltinPackage { @@ -96,21 +144,20 @@ public class BasePackage extends RBuiltinPackage { */ add(UnaryNotNode.class, UnaryNotNodeGen::create); - add(BinaryArithmetic.AddBuiltin.class, arguments -> BinaryArithmeticNodeGen.create(BinaryArithmetic.ADD, UnaryArithmetic.PLUS, arguments)); - add(BinaryArithmetic.SubtractBuiltin.class, - arguments -> BinaryArithmeticNodeGen.create(BinaryArithmetic.SUBTRACT, UnaryArithmetic.NEGATE, arguments)); - add(BinaryArithmetic.DivBuiltin.class, arguments -> BinaryArithmeticNodeGen.create(BinaryArithmetic.DIV, null, arguments)); - add(BinaryArithmetic.IntegerDivBuiltin.class, arguments -> BinaryArithmeticNodeGen.create(BinaryArithmetic.INTEGER_DIV, null, arguments)); - add(BinaryArithmetic.ModBuiltin.class, arguments -> BinaryArithmeticNodeGen.create(BinaryArithmetic.MOD, null, arguments)); - add(BinaryArithmetic.MultiplyBuiltin.class, arguments -> BinaryArithmeticNodeGen.create(BinaryArithmetic.MULTIPLY, null, arguments)); - add(BinaryArithmetic.PowBuiltin.class, arguments -> BinaryArithmeticNodeGen.create(BinaryArithmetic.POW, null, arguments)); + addBinaryArithmetic(BinaryArithmetic.AddBuiltin.class, BinaryArithmetic.ADD, UnaryArithmetic.PLUS); + addBinaryArithmetic(BinaryArithmetic.SubtractBuiltin.class, BinaryArithmetic.SUBTRACT, UnaryArithmetic.NEGATE); + addBinaryArithmetic(BinaryArithmetic.DivBuiltin.class, BinaryArithmetic.DIV, null); + addBinaryArithmetic(BinaryArithmetic.IntegerDivBuiltin.class, BinaryArithmetic.INTEGER_DIV, null); + addBinaryArithmetic(BinaryArithmetic.ModBuiltin.class, BinaryArithmetic.MOD, null); + addBinaryArithmetic(BinaryArithmetic.MultiplyBuiltin.class, BinaryArithmetic.MULTIPLY, null); + addBinaryArithmetic(BinaryArithmetic.PowBuiltin.class, BinaryArithmetic.POW, null); - add(BinaryCompare.EqualBuiltin.class, arguments -> BinaryBooleanNodeGen.create(BinaryCompare.EQUAL, arguments)); - add(BinaryCompare.NotEqualBuiltin.class, arguments -> BinaryBooleanNodeGen.create(BinaryCompare.NOT_EQUAL, arguments)); - add(BinaryCompare.GreaterEqualBuiltin.class, arguments -> BinaryBooleanNodeGen.create(BinaryCompare.GREATER_EQUAL, arguments)); - add(BinaryCompare.GreaterBuiltin.class, arguments -> BinaryBooleanNodeGen.create(BinaryCompare.GREATER_THAN, arguments)); - add(BinaryCompare.LessBuiltin.class, arguments -> BinaryBooleanNodeGen.create(BinaryCompare.LESS_THAN, arguments)); - add(BinaryCompare.LessEqualBuiltin.class, arguments -> BinaryBooleanNodeGen.create(BinaryCompare.LESS_EQUAL, arguments)); + addBinaryCompare(BinaryCompare.EqualBuiltin.class, BinaryCompare.EQUAL); + addBinaryCompare(BinaryCompare.NotEqualBuiltin.class, BinaryCompare.NOT_EQUAL); + addBinaryCompare(BinaryCompare.GreaterEqualBuiltin.class, BinaryCompare.GREATER_EQUAL); + addBinaryCompare(BinaryCompare.GreaterBuiltin.class, BinaryCompare.GREATER_THAN); + addBinaryCompare(BinaryCompare.LessBuiltin.class, BinaryCompare.LESS_THAN); + addBinaryCompare(BinaryCompare.LessEqualBuiltin.class, BinaryCompare.LESS_EQUAL); add(BinaryLogic.AndBuiltin.class, arguments -> BinaryBooleanNodeGen.create(BinaryLogic.AND, arguments)); add(BinaryLogic.OrBuiltin.class, arguments -> BinaryBooleanNodeGen.create(BinaryLogic.OR, arguments)); @@ -164,12 +211,12 @@ public class BasePackage extends RBuiltinPackage { add(BrowserFunctions.BrowserSetDebug.class, BrowserFunctionsFactory.BrowserSetDebugNodeGen::create); add(BrowserFunctions.BrowserText.class, BrowserFunctionsFactory.BrowserTextNodeGen::create); add(Call.class, CallNodeGen::create); - add(CapabilitiesFunctions.Capabilities.class, CapabilitiesFunctionsFactory.CapabilitiesNodeGen::create); + add(Capabilities.class, CapabilitiesNodeGen::create); add(Cat.class, CatNodeGen::create); add(Ceiling.class, CeilingNodeGen::create); add(CharMatch.class, CharMatchNodeGen::create); add(Col.class, ColNodeGen::create); - add(ColonNode.class, ColonNodeGen::create); + add(Colon.class, ColonNodeGen::create); add(ColMeans.class, ColMeansNodeGen::create); add(ColSums.class, ColSumsNodeGen::create); add(Combine.class, CombineNodeGen::create); @@ -272,10 +319,12 @@ public class BasePackage extends RBuiltinPackage { add(EnvFunctions.Search.class, EnvFunctionsFactory.SearchNodeGen::create); add(EnvFunctions.SetParentEnv.class, EnvFunctionsFactory.SetParentEnvNodeGen::create); add(EnvFunctions.UnlockBinding.class, EnvFunctionsFactory.UnlockBindingNodeGen::create); - add(EvalFunctions.Eval.class, EvalFunctionsFactory.EvalNodeGen::create); + add(Eval.class, EvalNodeGen::create); add(WithVisible.class, WithVisibleNodeGen::create); add(Exists.class, ExistsNodeGen::create); add(Expression.class, ExpressionNodeGen::create); + add(FastRContext.R.class, FastRContextFactory.RNodeGen::create); + add(FastRContext.Rscript.class, FastRContextFactory.RscriptNodeGen::create); add(FastRContext.CloseChannel.class, FastRContextFactory.CloseChannelNodeGen::create); add(FastRContext.CreateChannel.class, FastRContextFactory.CreateChannelNodeGen::create); add(FastRContext.Eval.class, FastRContextFactory.EvalNodeGen::create); @@ -289,17 +338,20 @@ public class BasePackage extends RBuiltinPackage { add(FastRContext.Join.class, FastRContextFactory.JoinNodeGen::create); add(FastrDqrls.class, FastrDqrlsNodeGen::create); add(FastRDebug.class, FastRDebugNodeGen::create); - add(FastRFunctionProfiler.Create.class, FastRFunctionProfilerFactory.CreateNodeGen::create); - add(FastRFunctionProfiler.Get.class, FastRFunctionProfilerFactory.GetNodeGen::create); - add(FastRFunctionProfiler.Reset.class, FastRFunctionProfilerFactory.ResetNodeGen::create); - add(FastRFunctionProfiler.Clear.class, FastRFunctionProfilerFactory.ClearNodeGen::create); add(FastRIdentity.class, FastRIdentityNodeGen::create); add(FastRInspect.class, FastRInspectNodeGen::create); add(FastRInterop.Eval.class, FastRInteropFactory.EvalNodeGen::create); add(FastRInterop.Export.class, FastRInteropFactory.ExportNodeGen::create); + add(FastRInterop.HasSize.class, FastRInteropFactory.HasSizeNodeGen::create); add(FastRInterop.Import.class, FastRInteropFactory.ImportNodeGen::create); + add(FastRInterop.IsNull.class, FastRInteropFactory.IsNullNodeGen::create); + add(FastRInterop.IsExecutable.class, FastRInteropFactory.IsExecutableNodeGen::create); + add(FastRInterop.ToBoolean.class, FastRInteropFactory.ToBooleanNodeGen::create); add(FastRRefCountInfo.class, FastRRefCountInfoNodeGen::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(FastRSyntaxTree.class, FastRSyntaxTreeNodeGen::create); add(FastRThrowIt.class, FastRThrowItNodeGen::create); add(FastRTrace.Trace.class, FastRTraceFactory.TraceNodeGen::create); @@ -374,28 +426,7 @@ public class BasePackage extends RBuiltinPackage { add(IConv.class, IConvNodeGen::create); add(Identical.class, Identical::create); add(NumericalFunctions.Im.class, NumericalFunctionsFactory.ImNodeGen::create); - add(InfixFunctions.AccessArraySubscriptBuiltin.class, InfixFunctionsFactory.AccessArraySubscriptBuiltinNodeGen::create); - add(InfixFunctions.AccessArraySubscriptDefaultBuiltin.class, InfixFunctionsFactory.AccessArraySubscriptBuiltinNodeGen::create); - add(InfixFunctions.AccessArraySubsetBuiltin.class, InfixFunctionsFactory.AccessArraySubsetBuiltinNodeGen::create); - add(InfixFunctions.AccessArraySubsetDefaultBuiltin.class, InfixFunctionsFactory.AccessArraySubsetBuiltinNodeGen::create); - add(InfixFunctions.AccessFieldBuiltin.class, InfixFunctionsFactory.AccessFieldBuiltinNodeGen::create); - add(InfixFunctions.AssignBuiltin.class, InfixFunctionsFactory.AssignBuiltinNodeGen::create); - add(InfixFunctions.AssignBuiltinEq.class, InfixFunctionsFactory.AssignBuiltinEqNodeGen::create); - add(InfixFunctions.AssignOuterBuiltin.class, InfixFunctionsFactory.AssignOuterBuiltinNodeGen::create); - add(InfixFunctions.BraceBuiltin.class, InfixFunctionsFactory.BraceBuiltinNodeGen::create); - add(InfixFunctions.BreakBuiltin.class, InfixFunctionsFactory.BreakBuiltinNodeGen::create); - add(InfixFunctions.ForBuiltin.class, InfixFunctionsFactory.ForBuiltinNodeGen::create); - add(InfixFunctions.FunctionBuiltin.class, InfixFunctionsFactory.FunctionBuiltinNodeGen::create); - add(InfixFunctions.IfBuiltin.class, InfixFunctionsFactory.IfBuiltinNodeGen::create); - add(InfixFunctions.NextBuiltin.class, InfixFunctionsFactory.NextBuiltinNodeGen::create); - add(InfixFunctions.ParenBuiltin.class, InfixFunctionsFactory.ParenBuiltinNodeGen::create); - add(InfixFunctions.RepeatBuiltin.class, InfixFunctionsFactory.RepeatBuiltinNodeGen::create); - add(InfixFunctions.TildeBuiltin.class, InfixFunctionsFactory.TildeBuiltinNodeGen::create); - add(InfixFunctions.UpdateArrayNodeSubscriptBuiltin.class, InfixFunctionsFactory.UpdateArrayNodeSubscriptBuiltinNodeGen::create); - add(InfixFunctions.UpdateArraySubsetBuiltin.class, InfixFunctionsFactory.UpdateArraySubsetBuiltinNodeGen::create); - add(InfixFunctions.UpdateFieldBuiltin.class, InfixFunctionsFactory.UpdateFieldBuiltinNodeGen::create); - add(InfixFunctions.WhileBuiltin.class, InfixFunctionsFactory.WhileBuiltinNodeGen::create); - add(Inherits.class, InheritsNodeGen::create); + add(InheritsBuiltin.class, InheritsBuiltinNodeGen::create); add(Interactive.class, InteractiveNodeGen::create); add(Internal.class, InternalNodeGen::create); add(IntToBits.class, IntToBitsNodeGen::create); @@ -566,6 +597,7 @@ public class BasePackage extends RBuiltinPackage { add(SysFunctions.SysInfo.class, SysFunctionsFactory.SysInfoNodeGen::create); add(SysFunctions.SysReadlink.class, SysFunctionsFactory.SysReadlinkNodeGen::create); add(SysFunctions.SysSetEnv.class, SysFunctionsFactory.SysSetEnvNodeGen::create); + add(SysFunctions.SysSetFileTime.class, SysFunctionsFactory.SysSetFileTimeNodeGen::create); add(SysFunctions.SysSleep.class, SysFunctionsFactory.SysSleepNodeGen::create); add(SysFunctions.SysTime.class, SysFunctionsFactory.SysTimeNodeGen::create); add(SysFunctions.SysUmask.class, SysFunctionsFactory.SysUmaskNodeGen::create); @@ -574,8 +606,8 @@ public class BasePackage extends RBuiltinPackage { add(Tabulate.class, TabulateNodeGen::create); add(TempDir.class, TempDirNodeGen::create); add(TempFile.class, TempFileNodeGen::create); - add(ToLowerOrUpper.ToLower.class, ToLowerOrUpper::createToLower); - add(ToLowerOrUpper.ToUpper.class, ToLowerOrUpper::createToUpper); + add(ToLowerOrUpper.ToLower.class, ToLowerOrUpperFactory.ToLowerNodeGen::create); + add(ToLowerOrUpper.ToUpper.class, ToLowerOrUpperFactory.ToUpperNodeGen::create); add(Traceback.class, TracebackNodeGen::create); add(TraceFunctions.PrimTrace.class, TraceFunctionsFactory.PrimTraceNodeGen::create); add(TraceFunctions.PrimUnTrace.class, TraceFunctionsFactory.PrimUnTraceNodeGen::create); @@ -624,9 +656,41 @@ public class BasePackage extends RBuiltinPackage { add(Vector.class, VectorNodeGen::create); add(Warning.class, WarningNodeGen::create); add(WhichFunctions.Which.class, WhichFunctionsFactory.WhichNodeGen::create); - add(WhichFunctions.WhichMax.class, WhichFunctionsFactory.WhichMaxNodeGen::create); - add(WhichFunctions.WhichMin.class, WhichFunctionsFactory.WhichMinNodeGen::create); + add(WhichFunctions.WhichMax.class, WhichFunctions.WhichMax::create); + add(WhichFunctions.WhichMin.class, WhichFunctions.WhichMin::create); add(Xtfrm.class, XtfrmNodeGen::create); + + // infix functions + add(Subscript.class, SubscriptNodeGen::create, Subscript::special); + add(Subscript.DefaultBuiltin.class, SubscriptNodeGen::create, Subscript::special); + add(Subset.class, SubsetNodeGen::create, Subset::special); + add(Subset.DefaultBuiltin.class, SubsetNodeGen::create, Subset::special); + add(AccessField.class, AccessFieldNodeGen::create, AccessField::createSpecial); + add(AssignBuiltin.class, AssignBuiltinNodeGen::create); + add(AssignBuiltinEq.class, AssignBuiltinEqNodeGen::create); + add(AssignOuterBuiltin.class, AssignOuterBuiltinNodeGen::create); + add(BraceBuiltin.class, BraceBuiltinNodeGen::create); + add(BreakBuiltin.class, BreakBuiltinNodeGen::create); + add(ForBuiltin.class, ForBuiltinNodeGen::create); + add(FunctionBuiltin.class, FunctionBuiltinNodeGen::create); + add(IfBuiltin.class, IfBuiltinNodeGen::create); + add(NextBuiltin.class, NextBuiltinNodeGen::create); + add(ParenBuiltin.class, ParenBuiltinNodeGen::create); + add(RepeatBuiltin.class, RepeatBuiltinNodeGen::create); + add(Tilde.class, TildeNodeGen::create); + add(UpdateSubscript.class, UpdateSubscriptNodeGen::create, UpdateSubset::special); + add(UpdateSubset.class, UpdateSubsetNodeGen::create, UpdateSubset::special); + add(UpdateField.class, UpdateFieldNodeGen::create); + add(WhileBuiltin.class, WhileBuiltinNodeGen::create); + } + + private void addBinaryArithmetic(Class<?> builtinClass, BinaryArithmeticFactory binaryFactory, UnaryArithmeticFactory unaryFactory) { + add(builtinClass, arguments -> BinaryArithmeticNodeGen.create(binaryFactory, unaryFactory, arguments), + BinaryArithmeticSpecial.createSpecialFactory(binaryFactory)); + } + + private void addBinaryCompare(Class<?> builtinClass, BooleanOperationFactory factory) { + add(builtinClass, arguments -> BinaryBooleanNodeGen.create(factory, arguments), BinaryBooleanSpecial.createSpecialFactory(factory)); } private static void addFastPath(MaterializedFrame baseFrame, String name, FastPathFactory factory) { @@ -634,7 +698,11 @@ public class BasePackage extends RBuiltinPackage { ((RRootNode) function.getRootNode()).setFastPath(factory); } - private static void addFastPath(MaterializedFrame baseFrame, String name, java.util.function.Supplier<RFastPathNode> factory, Class<?> builtinNodeClass) { + private static void addFastPath(MaterializedFrame baseFrame, String name, Supplier<RFastPathNode> factory, RVisibility visibility) { + addFastPath(baseFrame, name, FastPathFactory.fromVisibility(visibility, factory)); + } + + private static void addFastPath(MaterializedFrame baseFrame, String name, Supplier<RFastPathNode> factory, Class<?> builtinNodeClass) { RBuiltin builtin = builtinNodeClass.getAnnotation(RBuiltin.class); addFastPath(baseFrame, name, FastPathFactory.fromRBuiltin(builtin, factory)); } @@ -642,16 +710,16 @@ public class BasePackage extends RBuiltinPackage { @Override public void loadOverrides(MaterializedFrame baseFrame) { super.loadOverrides(baseFrame); - addFastPath(baseFrame, "matrix", () -> MatrixFastPathNodeGen.create(null), Matrix.class); - addFastPath(baseFrame, "setdiff", () -> SetDiffFastPathNodeGen.create(null)); - addFastPath(baseFrame, "get", () -> GetFastPathNodeGen.create(null)); - addFastPath(baseFrame, "exists", () -> ExistsFastPathNodeGen.create(null), Exists.class); - addFastPath(baseFrame, "assign", () -> AssignFastPathNodeGen.create(null), Assign.class); - addFastPath(baseFrame, "is.element", () -> IsElementFastPathNodeGen.create(null)); - addFastPath(baseFrame, "integer", () -> IntegerFastPathNodeGen.create(null)); - addFastPath(baseFrame, "numeric", () -> DoubleFastPathNodeGen.create(null)); - addFastPath(baseFrame, "double", () -> DoubleFastPathNodeGen.create(null)); - addFastPath(baseFrame, "intersect", () -> IntersectFastPathNodeGen.create(null)); + addFastPath(baseFrame, "matrix", MatrixFastPathNodeGen::create, Matrix.class); + addFastPath(baseFrame, "setdiff", SetDiffFastPathNodeGen::create, RVisibility.ON); + addFastPath(baseFrame, "get", GetFastPathNodeGen::create, RVisibility.ON); + addFastPath(baseFrame, "exists", ExistsFastPathNodeGen::create, Exists.class); + addFastPath(baseFrame, "assign", AssignFastPathNodeGen::create, Assign.class); + addFastPath(baseFrame, "is.element", IsElementFastPathNodeGen::create, RVisibility.ON); + addFastPath(baseFrame, "integer", IntegerFastPathNodeGen::create, RVisibility.ON); + addFastPath(baseFrame, "numeric", DoubleFastPathNodeGen::create, RVisibility.ON); + addFastPath(baseFrame, "double", DoubleFastPathNodeGen::create, RVisibility.ON); + addFastPath(baseFrame, "intersect", IntersectFastPathNodeGen::create, RVisibility.ON); addFastPath(baseFrame, "pmax", FastPathFactory.EVALUATE_ARGS); addFastPath(baseFrame, "pmin", FastPathFactory.EVALUATE_ARGS); addFastPath(baseFrame, "cbind", FastPathFactory.FORCED_EAGER_ARGS); 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 eed6487e7d200d01f870fc30c9c3217d6c11d3d1..24230ab782dd9c5f20a36b003f41380a6acb2c35 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 @@ -36,6 +36,7 @@ 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.RASTUtils; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode; import com.oracle.truffle.r.nodes.function.UseMethodInternalNode; @@ -68,7 +69,6 @@ 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.RVector; -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.na.NACheck; @@ -90,7 +90,7 @@ public abstract class Bind extends RBaseNode { protected static final int LIST_PRECEDENCE = PrecedenceNode.LIST_PRECEDENCE; protected static final int EXPRESSION_PRECEDENCE = PrecedenceNode.EXPRESSION_PRECEDENCE; - public abstract Object execute(VirtualFrame frame, Object deparseLevelObj, Object[] args, RArgsValuesAndNames promiseArgs, int precedence); + public abstract Object execute(VirtualFrame frame, int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, int precedence); @Child private CastToVectorNode castVector; @Child private UseMethodInternalNode dcn; @@ -139,7 +139,7 @@ public abstract class Bind extends RBaseNode { @SuppressWarnings("unused") @Specialization(guards = "precedence == NO_PRECEDENCE") - protected RNull allNull(VirtualFrame frame, Object deparseLevelObj, Object[] args, RArgsValuesAndNames promiseArgs, int precedence) { + protected RNull allNull(VirtualFrame frame, int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, int precedence) { return RNull.instance; } @@ -147,8 +147,8 @@ public abstract class Bind extends RBaseNode { private static final RStringVector DATA_FRAME_CLASS = RDataFactory.createStringVectorFromScalar("data.frame"); - @Specialization(guards = {"args.length > 1", "isDataFrame(args)"}) - protected Object allDataFrame(VirtualFrame frame, Object deparseLevel, @SuppressWarnings("unused") Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence) { + @Specialization(guards = {"args.length > 0", "isDataFrame(args)"}) + protected Object allDataFrame(VirtualFrame frame, int deparseLevel, @SuppressWarnings("unused") Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence) { if (dcn == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); dcn = insert(new UseMethodInternalNode(type.toString(), SIGNATURE, false)); @@ -160,7 +160,7 @@ public abstract class Bind extends RBaseNode { } } - private Object bindInternal(Object deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, CastNode castNode, boolean needsVectorCast) { + private Object bindInternal(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, CastNode castNode, boolean needsVectorCast) { ArgumentsSignature signature = promiseArgs.getSignature(); String[] vecNames = nullNamesProfile.profile(signature.getNonNullCount() == 0) ? null : new String[signature.getLength()]; RAbstractVector[] vectors = new RAbstractVector[args.length]; @@ -203,31 +203,31 @@ public abstract class Bind extends RBaseNode { } @Specialization(guards = {"precedence == INT_PRECEDENCE", "args.length > 1", "!isDataFrame(args)"}) - protected Object allInt(Object deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, // + protected Object allInt(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, // @Cached("create()") CastIntegerNode cast) { return bindInternal(deparseLevel, args, promiseArgs, cast, true); } @Specialization(guards = {"precedence == DOUBLE_PRECEDENCE", "args.length > 1", "!isDataFrame(args)"}) - protected Object allDouble(Object deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, // + protected Object allDouble(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, // @Cached("create()") CastDoubleNode cast) { return bindInternal(deparseLevel, args, promiseArgs, cast, true); } @Specialization(guards = {"precedence == STRING_PRECEDENCE", "args.length> 1", "!isDataFrame(args)"}) - protected Object allString(Object deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, // + protected Object allString(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, // @Cached("create()") CastStringNode cast) { return bindInternal(deparseLevel, args, promiseArgs, cast, true); } @Specialization(guards = {"precedence == COMPLEX_PRECEDENCE", "args.length > 1", "!isDataFrame(args)"}) - protected Object allComplex(Object deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, // + protected Object allComplex(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, // @Cached("create()") CastComplexNode cast) { return bindInternal(deparseLevel, args, promiseArgs, cast, true); } @Specialization(guards = {"precedence == LIST_PRECEDENCE", "args.length > 1", "!isDataFrame(args)"}) - protected Object allList(Object deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, // + protected Object allList(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, // @Cached("create()") CastListNode cast) { return bindInternal(deparseLevel, args, promiseArgs, cast, false); } @@ -267,7 +267,7 @@ public abstract class Bind extends RBaseNode { * Compute dimnames for columns (cbind) or rows (rbind) from names of vectors being combined or * by deparsing. */ - protected int getDimResultNamesFromVectors(RArgsValuesAndNames promiseArgs, RAbstractVector vec, String[] argNames, int resDim, int oldInd, int vecInd, Object deparseLevelObj, + protected int getDimResultNamesFromVectors(RArgsValuesAndNames promiseArgs, RAbstractVector vec, String[] argNames, int resDim, int oldInd, int vecInd, int deparseLevel, String[] dimNamesArray, int dimNamesInd) { int ind = oldInd; @@ -294,7 +294,6 @@ public abstract class Bind extends RBaseNode { return -ind; } else if (!vec.isArray() || vec.getDimensions().length == 1) { if (argNames == null) { - int deparseLevel = deparseLevel(deparseLevelObj); if (deparseLevel == 0) { dimNamesArray[ind++] = RRuntime.NAMES_ATTR_EMPTY_VALUE; return -ind; @@ -350,15 +349,6 @@ public abstract class Bind extends RBaseNode { return notEqualDims; } - protected int deparseLevel(Object deparseLevelObj) { - RAbstractLogicalVector v = (RAbstractLogicalVector) castLogical(castVector(deparseLevelObj), true); - if (v.getLength() == 0 || v.getDataAt(0) == 0) { - return 0; - } else { - return v.getDataAt(0); - } - } - protected int[] getDimensions(RAbstractVector vector) { int[] dimensions = vector.getDimensions(); if (dimensions == null || dimensions.length != 2) { @@ -375,7 +365,7 @@ public abstract class Bind extends RBaseNode { Object argValue = promiseArgs.getArgument(argInd); if (argValue instanceof RPromise) { RPromise p = (RPromise) argValue; - Object node = RASTUtils.createLanguageElement(RASTUtils.unwrap(p.getRep())); + Object node = RASTUtils.createLanguageElement(p.getRep().asRSyntaxNode()); if (deparseLevel == 1 && node instanceof RSymbol) { return ((RSymbol) node).toString(); } // else - TODO handle deparseLevel > 1 @@ -404,6 +394,11 @@ public abstract class Bind extends RBaseNode { @Child private Bind bind = BindNodeGen.create(BindType.cbind); @Child private PrecedenceNode precedenceNode = PrecedenceNodeGen.create(); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("deparse.level").asIntegerVector().findFirst(0); + } + private int precedence(Object[] args) { int precedence = -1; for (int i = 0; i < args.length; i++) { @@ -413,8 +408,8 @@ public abstract class Bind extends RBaseNode { } @Specialization - protected Object bind(VirtualFrame frame, Object deparseLevelObj, RArgsValuesAndNames args) { - return bind.execute(frame, deparseLevelObj, args.getArguments(), (RArgsValuesAndNames) RArguments.getArgument(frame, 0), precedence(args.getArguments())); + protected Object bind(VirtualFrame frame, int deparseLevel, RArgsValuesAndNames args) { + return bind.execute(frame, deparseLevel, args.getArguments(), (RArgsValuesAndNames) RArguments.getArgument(frame, 0), precedence(args.getArguments())); } } @@ -422,7 +417,7 @@ public abstract class Bind extends RBaseNode { private final BranchProfile everSeenNotEqualColumns = BranchProfile.create(); @Specialization(guards = {"precedence != NO_PRECEDENCE", "args.length == 1"}) - protected Object allOneElem(Object deparseLevelObj, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence) { + protected Object allOneElem(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence) { RAbstractVector vec = castVector(args[0]); if (vec.isMatrix()) { return vec; @@ -435,7 +430,6 @@ public abstract class Bind extends RBaseNode { ArgumentsSignature signature = promiseArgs.getSignature(); if (signature.getNonNullCount() == 0) { - int deparseLevel = deparseLevel(deparseLevelObj); if (deparseLevel == 0) { dimNamesB = RNull.instance; } else { @@ -451,18 +445,18 @@ public abstract class Bind extends RBaseNode { dimNamesB = RDataFactory.createStringVector(names, RDataFactory.COMPLETE_VECTOR); } - RVector res = (RVector) vec.copyWithNewDimensions(dims); + RVector<?> res = (RVector<?>) vec.copyWithNewDimensions(dims); res.setDimNames(RDataFactory.createList(type == BindType.cbind ? new Object[]{dimNamesA, dimNamesB} : new Object[]{dimNamesB, dimNamesA})); res.copyRegAttributesFrom(vec); return res; } - public RVector genericCBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, boolean complete, String[] vecNames, boolean vecNamesComplete, Object deparseLevel) { + public RVector<?> genericCBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, boolean complete, String[] vecNames, boolean vecNamesComplete, int deparseLevel) { int[] resultDimensions = new int[2]; int[] secondDims = new int[vectors.length]; boolean notEqualRows = getResultDimensions(vectors, resultDimensions, secondDims); - RVector result = resultProfile.profile(vectors[0].createEmptySameType(resultDimensions[0] * resultDimensions[1], complete)); + RVector<?> result = resultProfile.profile(vectors[0].createEmptySameType(resultDimensions[0] * resultDimensions[1], complete)); int ind = 0; Object rowDimResultNames = RNull.instance; @@ -518,6 +512,11 @@ public abstract class Bind extends RBaseNode { @Child private Bind bind = BindNodeGen.create(BindType.rbind); @Child private PrecedenceNode precedenceNode = PrecedenceNodeGen.create(); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("deparse.level").asIntegerVector().findFirst(0); + } + private int precedence(Object[] args) { int precedence = -1; for (int i = 0; i < args.length; i++) { @@ -527,17 +526,17 @@ public abstract class Bind extends RBaseNode { } @Specialization - protected Object bind(VirtualFrame frame, Object deparseLevelObj, RArgsValuesAndNames args) { - return bind.execute(frame, deparseLevelObj, args.getArguments(), (RArgsValuesAndNames) RArguments.getArgument(frame, 0), precedence(args.getArguments())); + protected Object bind(VirtualFrame frame, int deparseLevel, RArgsValuesAndNames args) { + return bind.execute(frame, deparseLevel, args.getArguments(), (RArgsValuesAndNames) RArguments.getArgument(frame, 0), precedence(args.getArguments())); } } - public RVector genericRBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, boolean complete, String[] vecNames, boolean vecNamesComplete, Object deparseLevel) { + public RVector<?> genericRBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, boolean complete, String[] vecNames, boolean vecNamesComplete, int deparseLevel) { int[] resultDimensions = new int[2]; int[] firstDims = new int[vectors.length]; boolean notEqualColumns = getResultDimensions(vectors, resultDimensions, firstDims); - RVector result = resultProfile.profile(vectors[0].createEmptySameType(resultDimensions[0] * resultDimensions[1], complete)); + RVector<?> result = resultProfile.profile(vectors[0].createEmptySameType(resultDimensions[0] * resultDimensions[1], complete)); Object colDimResultNames = RNull.instance; String[] rowDimNamesArray = new String[resultDimensions[0]]; 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 2661b83fdd58b015a5f6e1a1757614aa112ffd72..91ae3bcef8477a3601a7730d84f3fb443f90213a 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 @@ -11,25 +11,34 @@ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.anyValue; +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.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.shouldBe; +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; +import java.util.function.Function; + +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.LoopConditionProfile; -import com.oracle.truffle.r.nodes.binary.CastTypeNode; -import com.oracle.truffle.r.nodes.binary.CastTypeNodeGen; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.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.RDataFactory; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +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.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -37,13 +46,10 @@ public class BitwiseFunctions { public abstract static class BasicBitwise extends RBuiltinNode { - private final BranchProfile errorProfile = BranchProfile.create(); private final NACheck naCheckA = NACheck.create(); private final NACheck naCheckB = NACheck.create(); private final LoopConditionProfile loopProfile = LoopConditionProfile.createCountingProfile(); - @Child private CastTypeNode castTypeA = CastTypeNodeGen.create(null, null); - @Child private CastTypeNode castTypeB = CastTypeNodeGen.create(null, null); @Child private TypeofNode typeofA = TypeofNodeGen.create(); @Child private TypeofNode typeofB = TypeofNodeGen.create(); @@ -62,10 +68,7 @@ public class BitwiseFunctions { } } - protected Object basicBit(RAbstractVector a, RAbstractVector b, Operation op) { - checkBasicBit(a, b, op); - RAbstractIntVector aVec = (RAbstractIntVector) castTypeA.execute(a, RType.Integer); - RAbstractIntVector bVec = (RAbstractIntVector) castTypeB.execute(b, RType.Integer); + protected Object basicBit(RAbstractIntVector aVec, RAbstractIntVector bVec, Operation op) { naCheckA.enable(aVec); naCheckB.enable(bVec); int aLen = aVec.getLength(); @@ -119,8 +122,7 @@ public class BitwiseFunctions { return RDataFactory.createIntVector(ans, completeVector); } - protected Object bitNot(RAbstractVector a) { - RAbstractIntVector aVec = (RAbstractIntVector) castTypeA.execute(a, RType.Integer); + protected Object bitNot(RAbstractIntVector aVec) { int[] ans = new int[aVec.getLength()]; for (int i = 0; i < aVec.getLength(); i++) { ans[i] = ~aVec.getDataAt(i); @@ -136,107 +138,146 @@ public class BitwiseFunctions { return RDataFactory.createIntVector(na, RDataFactory.INCOMPLETE_VECTOR); } - protected void checkBasicBit(RAbstractVector a, RAbstractVector b, Operation op) { - hasSameTypes(a, b); - hasSupportedType(a, op); - } - - protected void checkShiftOrNot(RAbstractVector a, Operation op) { - hasSupportedType(a, op); - } - - protected void hasSameTypes(RAbstractVector a, RAbstractVector b) { - RType aType = typeofA.execute(a); - RType bType = typeofB.execute(b); - boolean aCorrectType = (aType == RType.Integer || aType == RType.Double) ? true : false; - boolean bCorrectType = (bType == RType.Integer || bType == RType.Double) ? true : false; - if ((aCorrectType && bCorrectType) || aType == bType) { - return; - } else { - errorProfile.enter(); - throw RError.error(this, RError.Message.SAME_TYPE, "a", "b"); - } - } - - protected void hasSupportedType(RAbstractVector a, Operation op) { - if (!(a instanceof RAbstractIntVector) && !(a instanceof RAbstractDoubleVector)) { - errorProfile.enter(); - String type = typeofA.execute(a).getName(); - throw RError.error(this, RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, type, op.name); - } + protected Function<Object, String> getArgType() { + return x -> typeofA.execute(x).getName(); } - protected boolean shiftByCharacter(RAbstractVector n) { - return typeofB.execute(n) == RType.Character; - } } @RBuiltin(name = "bitwiseAnd", kind = INTERNAL, parameterNames = {"a", "b"}, behavior = PURE) public abstract static class BitwiseAnd extends BasicBitwise { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.AND.name).mustBe(doubleValue().or(integerValue())).asIntegerVector(); + casts.arg("b").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.AND.name).mustBe(doubleValue().or(integerValue())).asIntegerVector(); + } + @Specialization - protected Object bitwAnd(RAbstractVector a, RAbstractVector b) { + protected Object bitwAnd(RAbstractIntVector a, RAbstractIntVector b) { return basicBit(a, b, Operation.AND); } + + @Fallback + @SuppressWarnings("unused") + protected Object differentTypes(Object a, Object b) { + throw RError.error(this, RError.Message.SAME_TYPE, "a", "b"); + } + } @RBuiltin(name = "bitwiseOr", kind = INTERNAL, parameterNames = {"a", "b"}, behavior = PURE) public abstract static class BitwiseOr extends BasicBitwise { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.OR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector(); + casts.arg("b").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.OR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector(); + } + @Specialization - protected Object bitwOr(RAbstractVector a, RAbstractVector b) { + protected Object bitwOr(RAbstractIntVector a, RAbstractIntVector b) { return basicBit(a, b, Operation.OR); } + + @Fallback + @SuppressWarnings("unused") + protected Object differentTypes(Object a, Object b) { + throw RError.error(this, RError.Message.SAME_TYPE, "a", "b"); + } } @RBuiltin(name = "bitwiseXor", kind = INTERNAL, parameterNames = {"a", "b"}, behavior = PURE) public abstract static class BitwiseXor extends BasicBitwise { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.XOR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector(); + casts.arg("b").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.XOR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector(); + } + @Specialization - protected Object bitwXor(RAbstractVector a, RAbstractVector b) { + protected Object bitwXor(RAbstractIntVector a, RAbstractIntVector b) { return basicBit(a, b, Operation.XOR); } + + @Fallback + @SuppressWarnings("unused") + protected Object differentTypes(Object a, Object b) { + throw RError.error(this, RError.Message.SAME_TYPE, "a", "b"); + } } @RBuiltin(name = "bitwiseShiftR", kind = INTERNAL, parameterNames = {"a", "n"}, behavior = PURE) public abstract static class BitwiseShiftR extends BasicBitwise { - @Specialization(guards = {"!shiftByCharacter(n)"}) - protected Object bitwShiftR(RAbstractVector a, RAbstractVector n) { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.SHIFTR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector(); + casts.arg("n").mapIf(stringValue(), asStringVector(), asIntegerVector()); + } + + @Specialization + protected Object bitwShiftR(RAbstractIntVector a, RAbstractIntVector n) { return basicBit(a, n, Operation.SHIFTR); } - @Specialization(guards = {"shiftByCharacter(n)"}) + @Specialization + @SuppressWarnings("unused") + protected Object bitwShiftR(RAbstractIntVector a, RNull n) { + return RDataFactory.createEmptyIntVector(); + } + + @Specialization @SuppressWarnings("unused") - protected Object bitwShiftRChar(RAbstractVector a, RAbstractVector n) { - checkShiftOrNot(a, Operation.SHIFTR); + protected Object bitwShiftRChar(RAbstractIntVector a, RAbstractStringVector n) { return makeNA(a.getLength()); } + } @RBuiltin(name = "bitwiseShiftL", kind = INTERNAL, parameterNames = {"a", "n"}, behavior = PURE) public abstract static class BitwiseShiftL extends BasicBitwise { - @Specialization(guards = {"!shiftByCharacter(n)"}) - protected Object bitwShiftR(RAbstractVector a, RAbstractVector n) { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("a").defaultError(RError.ROOTNODE, RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), 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()); + } + + @Specialization + protected Object bitwShiftL(RAbstractIntVector a, RAbstractIntVector n) { return basicBit(a, n, Operation.SHIFTL); } - @Specialization(guards = {"shiftByCharacter(n)"}) + @Specialization @SuppressWarnings("unused") - protected Object bitwShiftRChar(RAbstractVector a, RAbstractVector n) { - checkShiftOrNot(a, Operation.SHIFTL); + 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 { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.NOT.name).mustBe(doubleValue().or(integerValue())).asIntegerVector(); + } + @Specialization - protected Object bitwNot(RAbstractVector a) { - checkShiftOrNot(a, Operation.NOT); + protected Object bitwNot(RAbstractIntVector a) { return bitNot(a); } + } } 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 7533186dd55b6c228eaab8c3fd92e954277aca6f..e852f86379df5b2dbd48b70d9c83c6c3dad45227 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 @@ -39,7 +39,7 @@ public abstract class Body extends RBuiltinNode { @Specialization protected Object doBody(RFunction fun) { FunctionDefinitionNode fdn = (FunctionDefinitionNode) fun.getRootNode(); - return RASTUtils.createLanguageElement(fdn.getBody().asRNode()); + return RASTUtils.createLanguageElement(fdn.getBody()); } @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 ce2427e8087414c5b0958463e42b31a028008c09..ad9719fc6246daea404f44b2ee6eeeb28e765947 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,13 +22,12 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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.INTERNAL; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; -import java.util.ArrayList; - import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.MaterializedFrame; @@ -45,22 +44,11 @@ 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.RNull; +import com.oracle.truffle.r.runtime.instrument.InstrumentationState.BrowserState; +import com.oracle.truffle.r.runtime.instrument.InstrumentationState.BrowserState.HelperState; public class BrowserFunctions { - private static final class HelperState { - - private final String text; - private final Object condition; - - private HelperState(String text, Object condition) { - this.text = text; - this.condition = condition; - } - } - - private static final ArrayList<HelperState> helperState = new ArrayList<>(); - @RBuiltin(name = "browser", visibility = OFF, kind = PRIMITIVE, parameterNames = {"text", "condition", "expr", "skipCalls"}, behavior = COMPLEX) public abstract static class BrowserNode extends RBuiltinNode { @@ -73,48 +61,56 @@ public class BrowserFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(3); + // TODO: add support for conditions conditions + casts.arg("condition").allowNull().mustBe(anyValue().not(), RError.Message.GENERIC, "Only NULL conditions currently supported in browser"); + casts.arg("expr").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + casts.arg("skipCalls").asIntegerVector().findFirst(0); } @SuppressWarnings("unused") @Specialization - protected RNull browser(VirtualFrame frame, String text, RNull condition, byte expr, int skipCalls) { - if (RRuntime.fromLogical(expr)) { + protected RNull browser(VirtualFrame frame, Object text, RNull condition, boolean expr, int skipCalls) { + if (expr) { + BrowserState browserState = RContext.getInstance().stateInstrumentation.getBrowserState(); try { - helperState.add(new HelperState(text, condition)); + browserState.push(new HelperState(text, condition)); MaterializedFrame mFrame = frame.materialize(); RCaller caller = RArguments.getCall(mFrame); - String callerString; - if (caller == null) { - callerString = "top level"; - } else { - callerString = RContext.getRRuntimeASTAccess().getCallerSource(caller); - } - RContext.getInstance().getConsoleHandler().printf("Called from: %s%n", callerString); + doPrint(caller); browserInteractNode.execute(frame); } finally { - helperState.remove(helperState.size() - 1); + browserState.pop(); } } - RContext.getInstance().setVisible(false); return RNull.instance; } + + @TruffleBoundary + private static void doPrint(RCaller caller) { + String callerString; + if (caller == null || (!caller.isValidCaller() && caller.getDepth() == 0 && caller.getParent() == null)) { + callerString = "top level"; + } else { + callerString = RContext.getRRuntimeASTAccess().getCallerSource(caller); + } + RContext.getInstance().getConsoleHandler().printf("Called from: %s%n", callerString); + + } } private abstract static class RetrieveAdapter extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + 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) { - if (n <= 0) { - throw RError.error(this, Message.POSITIVE_CONTEXTS); - } - int nn = n; - if (nn > helperState.size()) { - nn = helperState.size(); - } - return helperState.get(nn - 1); + BrowserState helperState = RContext.getInstance().stateInstrumentation.getBrowserState(); + return helperState.get(n); } } @@ -123,15 +119,10 @@ public class BrowserFunctions { @Specialization @TruffleBoundary - protected String browserText(int n) { + protected Object browserText(int n) { return getHelperState(n).text; } - @Specialization - @TruffleBoundary - protected String browserText(double n) { - return getHelperState((int) n).text; - } } @RBuiltin(name = "browserCondition", kind = INTERNAL, parameterNames = {"n"}, behavior = COMPLEX) @@ -143,11 +134,6 @@ public class BrowserFunctions { return getHelperState(n).condition; } - @Specialization - @TruffleBoundary - protected Object browserCondition(double n) { - return getHelperState((int) n).condition; - } } @RBuiltin(name = "browserSetDebug", visibility = OFF, kind = INTERNAL, parameterNames = {"n"}, behavior = COMPLEX) @@ -157,7 +143,6 @@ public class BrowserFunctions { @TruffleBoundary protected RNull browserSetDebug(@SuppressWarnings("unused") int n) { // TODO implement - RContext.getInstance().setVisible(false); return RNull.instance; } } 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 9cf229dc3349778e0d333973263f9b1f6f128fd9..2d78a5d73a95e3fedc04ee23c03f1690f5ed03e1 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 @@ -31,6 +31,11 @@ public abstract class CacheClass extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { casts.arg("class").defaultError(RError.Message.GENERIC, "invalid class argument to internal .class_cache").mustBe(stringValue()).asStringVector().findFirst(); + // apparently, "extends" does not have to be a string vector (GNU R will not signal this + // error) - but it does not seem to make much sense and it's doubtful if it's worth + // supporting since this is internal function + casts.arg("extends").defaultError(RError.Message.GENERIC, "invalid extends argument to internal .class_cache").mustBe(stringValue()).asStringVector(); + } @TruffleBoundary 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 a1c627dc33ffa1fbd12b72ecd1a47ad6f8c70738..7283e1d26e2d3ca124338b64c6876c1a3cb64775 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 @@ -22,14 +22,15 @@ */ 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.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.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RError; @@ -39,7 +40,6 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; 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.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; /** @@ -55,15 +55,14 @@ public abstract class Call extends RBuiltinNode { return new Object[]{RMissing.instance, RArgsValuesAndNames.EMPTY}; } - @Specialization(guards = "name.getLength() != 0") - protected RLanguage call(RAbstractStringVector name, RArgsValuesAndNames args) { - return makeCall(name.getDataAt(0), args); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("").mustBe(stringValue(), RError.Message.FIRST_ARG_MUST_BE_STRING).asStringVector().findFirst(); } - @Fallback - @SuppressWarnings("unused") - protected RLanguage call(Object name, Object args) { - throw RError.error(this, RError.Message.FIRST_ARG_MUST_BE_STRING); + @Specialization + protected RLanguage call(String name, RArgsValuesAndNames args) { + return makeCall(name, args); } @TruffleBoundary 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 new file mode 100644 index 0000000000000000000000000000000000000000..ed3a304e2219e548468f707c80b0825736f427d2 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015, 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.builtin.base; + +import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE; +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.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.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RStringVector; + +@RBuiltin(name = "capabilities", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) +public abstract class Capabilities extends RBuiltinNode { + private enum Capability { + jpeg(false, null), + png(false, null), + tiff(false, null), + tcltk(false, null), + X11(false, null), + aqua(false, null), + http_fttp(true, "http/ftp"), + sockets(true, null), + libxml(false, null), + fifo(false, null), + cledit(false, null), + iconv(false, null), + nls(false, "NLS"), + profmem(false, null), + cairo(false, null); + + private final boolean defValue; + private final String rName; + + Capability(boolean defValue, String nameOverride) { + this.defValue = defValue; + this.rName = nameOverride == null ? name() : nameOverride; + } + + static String[] rNames() { + Capability[] values = values(); + String[] result = new String[values.length]; + for (Capability c : values) { + result[c.ordinal()] = c.rName; + } + return result; + } + + } + + private static final RStringVector NAMES = RDataFactory.createStringVector(Capability.rNames(), RDataFactory.COMPLETE_VECTOR); + + @Specialization + protected RLogicalVector capabilities() { + byte[] data = new byte[NAMES.getLength()]; + for (Capability c : Capability.values()) { + boolean value = c.defValue; + switch (c) { + case cledit: + value = RContext.getInstance().isInteractive() && !RContext.getInstance().getStartParams().getNoReadline(); + break; + } + data[c.ordinal()] = RRuntime.asLogical(value); + } + return RDataFactory.createLogicalVector(data, RDataFactory.COMPLETE_VECTOR, NAMES); + } +} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CapabilitiesFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CapabilitiesFunctions.java deleted file mode 100644 index 32cd5b8d6140411a6b000c9773b08c697218489d..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CapabilitiesFunctions.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2015, 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.builtin.base; - -import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE; -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.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.RLogicalVector; -import com.oracle.truffle.r.runtime.data.RStringVector; - -public class CapabilitiesFunctions { - - @RBuiltin(name = "capabilities", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) - public abstract static class Capabilities extends RBuiltinNode { - private enum Capability { - jpeg(false, null), - png(false, null), - tiff(false, null), - tcltk(false, null), - X11(false, null), - aqua(false, null), - http_fttp(true, "http/ftp"), - sockets(true, null), - libxml(false, null), - fifo(false, null), - cledit(false, null), - iconv(false, null), - nls(false, "NLS"), - profmem(false, null), - cairo(false, null); - - private final boolean defValue; - private final String rName; - - Capability(boolean defValue, String nameOverride) { - this.defValue = defValue; - this.rName = nameOverride == null ? name() : nameOverride; - } - - static String[] rNames() { - Capability[] values = values(); - String[] result = new String[values.length]; - for (Capability c : values) { - result[c.ordinal()] = c.rName; - } - return result; - } - - } - - private static final RStringVector NAMES = RDataFactory.createStringVector(Capability.rNames(), RDataFactory.COMPLETE_VECTOR); - - @Specialization - protected RLogicalVector capabilities() { - byte[] data = new byte[NAMES.getLength()]; - for (Capability c : Capability.values()) { - boolean value = c.defValue; - switch (c) { - case cledit: - value = RContext.getInstance().isInteractive() && !RContext.getInstance().getStartParams().getNoReadline(); - break; - } - data[c.ordinal()] = RRuntime.asLogical(value); - } - return RDataFactory.createLogicalVector(data, RDataFactory.COMPLETE_VECTOR, NAMES); - } - } -} 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 820ebe68374842f7955c7060ed0fea3dffdbd603..3694e0b31197c471216607ab32024188273268f6 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 @@ -24,14 +24,13 @@ package com.oracle.truffle.r.nodes.builtin.base; 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.defaultValue; 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.nullValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicLogicalValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.scalarLogicalValue; 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.emptyStringVector; 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.IO; @@ -79,10 +78,11 @@ public abstract class Cat extends RBuiltinNode { protected void createCasts(CastBuilder casts) { casts.arg("sep").mustBe(stringValue(), RError.Message.INVALID_SEP); - casts.arg("fill").mustBe(numericValue()).asVector().mustBe(singleElement()).findFirst().mustBe(nullValue().not()).shouldBe(instanceOf(Byte.class).or(instanceOf(Integer.class).and(gt0())), - Message.NON_POSITIVE_FILL).mapIf(scalarLogicalValue(), asBoolean(), asInteger()); + 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("labels").map(defaultValue(RDataFactory.createStringVector(0))).mustBe(stringValue()).asStringVector(); + casts.arg("labels").mapNull(emptyStringVector()).mustBe(stringValue()).asStringVector(); // append is interpreted in the calling closure, but GnuR still checks for NA casts.arg("append").asLogicalVector().findFirst().map(toBoolean()); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java index 1d60402d1004bbcfec766753ad8b3155ed768797..9ea6d639e41d4cb7cd13c94ed6e09b860809b807 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java @@ -22,39 +22,64 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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 com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode; -import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNode; -import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNodeGen; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; +import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode; import com.oracle.truffle.r.runtime.RError; 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.ops.UnaryArithmeticFactory; @RBuiltin(name = "ceiling", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) -public abstract class Ceiling extends RBuiltinNode { +public abstract class Ceiling extends UnaryArithmeticBuiltinNode { - public static final UnaryArithmeticFactory CEILING = CeilingArithmetic::new; + public static final UnaryArithmeticFactory CEILING = FloorNodeGen.create(null); - @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create(); - @Child private UnaryArithmeticNode ceiling = UnaryArithmeticNodeGen.create(CEILING, RError.Message.NON_NUMERIC_MATH, RType.Double); + public Ceiling() { + super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null); + } - @Specialization - protected Object ceiling(Object value) { - return ceiling.execute(boxPrimitive.execute(value)); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustNotBeNull(this, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).asDoubleVector(); + } + + @Override + public int op(byte op) { + return op; } - private static final class CeilingArithmetic extends Round.RoundArithmetic { + @Override + public int op(int op) { + return op; + } + + @Override + public double op(double op) { + return Math.ceil(op); + } - @Override - public double op(double op) { - return Math.ceil(op); - } + @Override + protected double opd(double re, double im) { + return op(re); } + + @Override + public RComplex op(double re, double im) { + return RDataFactory.createComplex(op(re), op(im)); + } + + @Specialization + @Override + public Object calculateUnboxed(Object op) { + return super.calculateUnboxed(op); + } + } 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 b8d013e51094dd52e3e76d33acc38b666c2f07a9..335418deeb7d23845198344b06c82f5850e81256 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 @@ -10,12 +10,15 @@ */ 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.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -27,6 +30,8 @@ public abstract class CharMatch extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { + 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("noMatch").asIntegerVector().findFirst(RRuntime.INT_NA); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Choose.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Choose.java index cac9ba5f4c1832f2195a3452f63d3a9dcf84c150..8550d93fb754556db7da34fc1b88871171a66b9b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Choose.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Choose.java @@ -22,6 +22,9 @@ */ 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.logicalValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -29,6 +32,7 @@ import java.util.function.IntToDoubleFunction; import java.util.function.IntUnaryOperator; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; @@ -38,6 +42,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; 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.RAbstractIntVector; +import com.oracle.truffle.r.runtime.ops.na.NACheck; /** * Binomial coefficients (n, k) for real n and integral k (rounded with warning). @@ -45,11 +50,17 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @RBuiltin(name = "choose", kind = INTERNAL, parameterNames = {"n", "k"}, behavior = PURE) public abstract class Choose extends RBuiltinNode { - // TODO: cast of logicals to integers + private final NACheck na = NACheck.create(); + + @Override + protected void createCasts(CastBuilder casts) { + 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()); + } @Specialization protected RAbstractDoubleVector doInts(RAbstractIntVector n, RAbstractIntVector k) { - // TODO: check overflow, return int vector if possible, otherwise specialize + // Note: we may check overflow, return int vector if possible, otherwise specialize // Note: may be useful to specialize on small n and k and do only integer arithmetic return choose(n.getLength(), idx -> (double) n.getDataAt(idx), k.getLength(), idx -> k.getDataAt(idx)); } @@ -87,17 +98,17 @@ public abstract class Choose extends RBuiltinNode { return (int) result; } - private static RAbstractDoubleVector choose(int nLength, IntToDoubleFunction getN, int kLength, IntUnaryOperator getK) { + private RAbstractDoubleVector choose(int nLength, IntToDoubleFunction getN, int kLength, IntUnaryOperator getK) { int resultLen = Math.max(nLength, kLength); - boolean complete = true; double[] result = new double[resultLen]; + na.enable(true); for (int i = 0, nIdx = 0, kIdx = 0; i < resultLen; i++) { result[i] = choose(getN.applyAsDouble(nIdx), getK.applyAsInt(kIdx)); - complete &= result[i] != RRuntime.DOUBLE_NA; + na.check(result[i]); nIdx = Utils.incMod(nIdx, nLength); kIdx = Utils.incMod(kIdx, kLength); } - return RDataFactory.createDoubleVector(result, complete); + return RDataFactory.createDoubleVector(result, na.neverSeenNA()); } private static double choose(double n, int ka) { 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 fdfb7fc3a832adea1877761167956f9836bae5e4..f01f18b8f3f6f998338bafb0c913656ad71cc18a 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 @@ -42,7 +42,7 @@ public abstract class Col extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.arg("dims").mustBe(nullValue().not().and(integerValue()), RError.Message.MATRIX_LIKE_REQUIRED, "col").asIntegerVector().mustBe(size(2)); + casts.arg("dims").defaultError(RError.SHOW_CALLER, 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/ColMeans.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColMeans.java index 518c42f361639a3b9265921b49be991dd66606ae..6ae864b0cfdb7f43aa704f9d8ff97b20891af380 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColMeans.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColMeans.java @@ -10,16 +10,10 @@ */ 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.toBoolean; 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.ConditionProfile; -import com.oracle.truffle.r.nodes.builtin.CastBuilder; -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; @@ -27,125 +21,14 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector; 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.ops.BinaryArithmetic; -import com.oracle.truffle.r.runtime.ops.na.NACheck; //Implements .colMeans @RBuiltin(name = "colMeans", kind = INTERNAL, parameterNames = {"X", "m", "n", "na.rm"}, behavior = PURE) -public abstract class ColMeans extends RBuiltinNode { +public abstract class ColMeans extends ColSumsBase { @Child private BinaryArithmetic add = BinaryArithmetic.ADD.create(); - private final NACheck na = NACheck.create(); - private final ConditionProfile vectorLengthProfile = ConditionProfile.createBinaryProfile(); - - @Override - protected void createCasts(CastBuilder casts) { - casts.arg("X").mustBe(numericValue(), RError.NO_CALLER, RError.Message.X_NUMERIC); - - casts.arg("m").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "n").asIntegerVector().findFirst().notNA(RError.NO_CALLER, RError.Message.VECTOR_SIZE_NA); - - casts.arg("n").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "p").asIntegerVector().findFirst().notNA(RError.NO_CALLER, RError.Message.VECTOR_SIZE_NA); - - casts.arg("na.rm").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "na.rm").asLogicalVector().findFirst().notNA().map(toBoolean()); - } - - private 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"); - } - } - - protected boolean isEmptyMatrix(int rowNum, int colNum) { - return rowNum == 0 && colNum == 0; - } - - @Specialization(guards = "isEmptyMatrix(rowNum, colNum)") - @SuppressWarnings("unused") - protected RDoubleVector colMeansEmptyMatrix(Object x, int rowNum, int colNum, boolean naRm) { - return RDataFactory.createEmptyDoubleVector(); - } - - @Specialization(guards = "!naRm") - protected RDoubleVector colMeansScalarNaRmFalse(double x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - if (vectorLengthProfile.profile(rowNum * colNum > 1)) { - throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X"); - } - - return RDataFactory.createDoubleVectorFromScalar(x); - } - - @Specialization(guards = "naRm") - protected RDoubleVector colMeansScalarNaRmTrue(double x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - if (vectorLengthProfile.profile(rowNum * colNum > 1)) { - throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X"); - } - - na.enable(x); - if (!na.check(x) && !Double.isNaN(x)) { - return RDataFactory.createDoubleVectorFromScalar(x); - } else { - return RDataFactory.createDoubleVectorFromScalar(Double.NaN); - } - } - - @Specialization(guards = "!naRm") - protected RDoubleVector colMeansScalarNaRmFalse(int x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - if (vectorLengthProfile.profile(rowNum * colNum > 1)) { - throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X"); - } - - na.enable(x); - if (!na.check(x)) { - return RDataFactory.createDoubleVectorFromScalar(x); - } else { - return RDataFactory.createDoubleVectorFromScalar(RRuntime.DOUBLE_NA); - } - } - - @Specialization(guards = "naRm") - protected RDoubleVector colMeansScalarNaRmTrue(int x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - if (vectorLengthProfile.profile(rowNum * colNum > 1)) { - throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X"); - } - - na.enable(x); - if (!na.check(x)) { - return RDataFactory.createDoubleVectorFromScalar(x); - } else { - return RDataFactory.createDoubleVectorFromScalar(Double.NaN); - } - } - - @Specialization(guards = "!naRm") - protected RDoubleVector colMeansScalarNaRmFalse(byte x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - if (vectorLengthProfile.profile(rowNum * colNum > 1)) { - throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X"); - } - - na.enable(x); - if (!na.check(x)) { - return RDataFactory.createDoubleVectorFromScalar(x); - } else { - return RDataFactory.createDoubleVectorFromScalar(RRuntime.DOUBLE_NA); - } - } - - @Specialization(guards = "naRm") - protected RDoubleVector colMeansScalarNaRmTrue(byte x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - if (vectorLengthProfile.profile(rowNum * colNum > 1)) { - throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X"); - } - - na.enable(x); - if (!na.check(x)) { - return RDataFactory.createDoubleVectorFromScalar(x); - } else { - return RDataFactory.createDoubleVectorFromScalar(Double.NaN); - } - } - @Specialization(guards = "!naRm") protected RDoubleVector colMeansNaRmFalse(RAbstractDoubleVector x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { checkVectorLength(x, rowNum, colNum); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.java index 23564e03eae97ff55fa53bd7554005217f87738a..03ffd7f62e25c5a16cefdbdab66521004ff3e158 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.java @@ -22,17 +22,12 @@ */ 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.toBoolean; 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.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; -import com.oracle.truffle.r.nodes.builtin.CastBuilder; -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; @@ -40,125 +35,15 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector; 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.ops.BinaryArithmetic; -import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "colSums", kind = INTERNAL, parameterNames = {"X", "m", "n", "na.rm"}, behavior = PURE) -public abstract class ColSums extends RBuiltinNode { +public abstract class ColSums extends ColSumsBase { @Child private BinaryArithmetic add = BinaryArithmetic.ADD.create(); - private final NACheck na = NACheck.create(); private final ConditionProfile removeNA = ConditionProfile.createBinaryProfile(); private final ValueProfile concreteVectorProfile = ValueProfile.createClassProfile(); - private final ConditionProfile vectorLengthProfile = ConditionProfile.createBinaryProfile(); - - @Override - protected void createCasts(CastBuilder casts) { - casts.arg("X").mustBe(numericValue(), RError.NO_CALLER, RError.Message.X_NUMERIC); - - casts.arg("m").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "n").asIntegerVector().findFirst().notNA(RError.NO_CALLER, RError.Message.VECTOR_SIZE_NA); - - casts.arg("n").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "p").asIntegerVector().findFirst().notNA(RError.NO_CALLER, RError.Message.VECTOR_SIZE_NA); - - casts.arg("na.rm").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "na.rm").asLogicalVector().findFirst().notNA().map(toBoolean()); - } - - private 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"); - } - } - - protected boolean isEmptyMatrix(int rowNum, int colNum) { - return rowNum == 0 && colNum == 0; - } - - @Specialization(guards = "isEmptyMatrix(rowNum, colNum)") - @SuppressWarnings("unused") - protected RDoubleVector colSumsEmptyMatrix(Object x, int rowNum, int colNum, boolean naRm) { - return RDataFactory.createEmptyDoubleVector(); - } - - @Specialization(guards = "!naRm") - protected RDoubleVector colSumsScalarNaRmFalse(double x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - if (vectorLengthProfile.profile(rowNum * colNum > 1)) { - throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X"); - } - - return RDataFactory.createDoubleVectorFromScalar(x); - } - - @Specialization(guards = "naRm") - protected RDoubleVector colSumsScalarNaRmTrue(double x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - if (vectorLengthProfile.profile(rowNum * colNum > 1)) { - throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X"); - } - - na.enable(x); - if (!na.check(x) && !Double.isNaN(x)) { - return RDataFactory.createDoubleVectorFromScalar(x); - } else { - return RDataFactory.createDoubleVectorFromScalar(Double.NaN); - } - } - - @Specialization(guards = "!naRm") - protected RDoubleVector colSumsScalarNaRmFalse(int x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - if (vectorLengthProfile.profile(rowNum * colNum > 1)) { - throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X"); - } - - na.enable(x); - if (!na.check(x)) { - return RDataFactory.createDoubleVectorFromScalar(x); - } else { - return RDataFactory.createDoubleVectorFromScalar(RRuntime.DOUBLE_NA); - } - } - - @Specialization(guards = "naRm") - protected RDoubleVector colSumsScalarNaRmTrue(int x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - if (vectorLengthProfile.profile(rowNum * colNum > 1)) { - throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X"); - } - - na.enable(x); - if (!na.check(x)) { - return RDataFactory.createDoubleVectorFromScalar(x); - } else { - return RDataFactory.createDoubleVectorFromScalar(Double.NaN); - } - } - - @Specialization(guards = "!naRm") - protected RDoubleVector colSumsScalarNaRmFalse(byte x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - if (vectorLengthProfile.profile(rowNum * colNum > 1)) { - throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X"); - } - - na.enable(x); - if (!na.check(x)) { - return RDataFactory.createDoubleVectorFromScalar(x); - } else { - return RDataFactory.createDoubleVectorFromScalar(RRuntime.DOUBLE_NA); - } - } - - @Specialization(guards = "naRm") - protected RDoubleVector colSumsScalarNaRmTrue(byte x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - if (vectorLengthProfile.profile(rowNum * colNum > 1)) { - throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X"); - } - - na.enable(x); - if (!na.check(x)) { - return RDataFactory.createDoubleVectorFromScalar(x); - } else { - return RDataFactory.createDoubleVectorFromScalar(Double.NaN); - } - } @Specialization protected RDoubleVector colSums(RAbstractDoubleVector x, int rowNum, int colNum, boolean rnaParam) { 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 new file mode 100644 index 0000000000000000000000000000000000000000..86d65c04da3c9a1f480b306ad8d39fe34c141687 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java @@ -0,0 +1,136 @@ +/* + * 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.builtin.base; + +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.Message.INVALID_ARGUMENT; + +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; +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.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.ops.na.NACheck; + +/** + * Base class that provides arguments handling and validation helper methods and trivial cases + * specializations shared between {@link RowSums}, {@link RowMeans}, {@link ColMeans}, + * {@link RowSums}. + */ +public abstract class ColSumsBase extends RBuiltinNode { + + protected final NACheck na = NACheck.create(); + private final ConditionProfile vectorLengthProfile = ConditionProfile.createBinaryProfile(); + + @Override + protected final void createCasts(CastBuilder casts) { + 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()); + } + + 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"); + } + } + + @Specialization(guards = {"rowNum == 0", "colNum == 0"}) + @SuppressWarnings("unused") + protected static RDoubleVector doEmptyMatrix(Object x, int rowNum, int colNum, boolean naRm) { + return RDataFactory.createEmptyDoubleVector(); + } + + @Specialization(guards = "!naRm") + protected final RDoubleVector doScalarNaRmFalse(double x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { + checkLengthOne(rowNum, colNum); + return RDataFactory.createDoubleVectorFromScalar(x); + } + + @Specialization(guards = "naRm") + protected final RDoubleVector doScalarNaRmTrue(double x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { + checkLengthOne(rowNum, colNum); + na.enable(x); + if (!na.check(x) && !Double.isNaN(x)) { + return RDataFactory.createDoubleVectorFromScalar(x); + } else { + return RDataFactory.createDoubleVectorFromScalar(Double.NaN); + } + } + + @Specialization(guards = "!naRm") + protected final RDoubleVector doScalarNaRmFalse(int x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { + checkLengthOne(rowNum, colNum); + na.enable(x); + if (!na.check(x)) { + return RDataFactory.createDoubleVectorFromScalar(x); + } else { + return RDataFactory.createDoubleVectorFromScalar(RRuntime.DOUBLE_NA); + } + } + + @Specialization(guards = "naRm") + protected final RDoubleVector doScalarNaRmTrue(int x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { + checkLengthOne(rowNum, colNum); + na.enable(x); + if (!na.check(x)) { + return RDataFactory.createDoubleVectorFromScalar(x); + } else { + return RDataFactory.createDoubleVectorFromScalar(Double.NaN); + } + } + + @Specialization(guards = "!naRm") + protected final RDoubleVector doScalarNaRmFalse(byte x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { + checkLengthOne(rowNum, colNum); + na.enable(x); + if (!na.check(x)) { + return RDataFactory.createDoubleVectorFromScalar(x); + } else { + return RDataFactory.createDoubleVectorFromScalar(RRuntime.DOUBLE_NA); + } + } + + @Specialization(guards = "naRm") + protected final RDoubleVector doScalarNaRmTrue(byte x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { + checkLengthOne(rowNum, colNum); + na.enable(x); + if (!na.check(x)) { + return RDataFactory.createDoubleVectorFromScalar(x); + } else { + return RDataFactory.createDoubleVectorFromScalar(Double.NaN); + } + } + + private void checkLengthOne(int rowNum, int colNum) { + if (vectorLengthProfile.profile(rowNum * colNum > 1)) { + throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X"); + } + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/ColonNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java similarity index 57% rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/ColonNode.java rename to com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java index ea4d74871de8b70c70c87123b73c6542a66f4122..4616f2f1fd6cfc159c59178b0522d2e83a62ee52 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/ColonNode.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.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.binary; +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; @@ -28,11 +28,14 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; 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.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.binary.ColonNodeGen.ColonCastNodeGen; -import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +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.RError; import com.oracle.truffle.r.runtime.RError.Message; @@ -41,90 +44,100 @@ 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; +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.ops.na.NACheck; @RBuiltin(name = ":", kind = PRIMITIVE, parameterNames = {"", ""}, behavior = PURE) -public abstract class ColonNode extends RBuiltinNode { +public abstract class Colon extends RBuiltinNode { - private final BranchProfile naCheckErrorProfile = BranchProfile.create(); - private final NACheck leftNA = NACheck.create(); - private final NACheck rightNA = NACheck.create(); + @Child private ColonCastNode leftCast = ColonCastNodeGen.create(); + @Child private ColonCastNode rightCast = ColonCastNodeGen.create(); + @Child private ColonInternal internal = ColonInternalNodeGen.create(); - @Override - protected void createCasts(CastBuilder casts) { - // These casts should not be custom, but they are very hard to get right in a generic way. - // Also, the proper warnings cannot be produced at the moment. - casts.custom(0, ColonCastNodeGen.create()).custom(1, ColonCastNodeGen.create()); + @Specialization + protected RSequence colon(Object left, Object right) { + return internal.execute(leftCast.execute(left), rightCast.execute(right)); } - private void naCheck(boolean na) { - if (na) { - naCheckErrorProfile.enter(); - throw RError.error(this, RError.Message.NA_OR_NAN); + @NodeInfo(cost = NodeCost.NONE) + abstract static class ColonInternal extends Node { + + 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(); + throw RError.error(this, RError.Message.NA_OR_NAN); + } } - } - @Specialization(guards = "left <= right") - protected RIntSequence colonAscending(int left, int right) { - leftNA.enable(left); - rightNA.enable(right); - naCheck(leftNA.check(left) || rightNA.check(right)); - return RDataFactory.createAscendingRange(left, right); - } + protected static double asDouble(int intValue) { + return intValue; + } - @Specialization(guards = "left > right") - protected RIntSequence colonDescending(int left, int right) { - leftNA.enable(left); - rightNA.enable(right); - naCheck(leftNA.check(left) || rightNA.check(right)); - return RDataFactory.createDescendingRange(left, right); - } + @Specialization(guards = "left <= right") + protected RIntSequence colonAscending(int left, int right) { + leftNA.enable(left); + rightNA.enable(right); + naCheck(leftNA.check(left) || rightNA.check(right)); + return RDataFactory.createAscendingRange(left, right); + } - @Specialization(guards = "asDouble(left) <= right") - protected RIntSequence colonAscending(int left, double right) { - leftNA.enable(left); - naCheck(leftNA.check(left) || RRuntime.isNAorNaN(right)); - return RDataFactory.createAscendingRange(left, (int) right); - } + @Specialization(guards = "left > right") + protected RIntSequence colonDescending(int left, int right) { + leftNA.enable(left); + rightNA.enable(right); + naCheck(leftNA.check(left) || rightNA.check(right)); + return RDataFactory.createDescendingRange(left, right); + } - @Specialization(guards = "asDouble(left) > right") - protected RIntSequence colonDescending(int left, double right) { - leftNA.enable(left); - naCheck(leftNA.check(left) || RRuntime.isNAorNaN(right)); - return RDataFactory.createDescendingRange(left, (int) right); - } + @Specialization(guards = "asDouble(left) <= right") + protected RIntSequence colonAscending(int left, double right) { + leftNA.enable(left); + naCheck(leftNA.check(left) || RRuntime.isNAorNaN(right)); + return RDataFactory.createAscendingRange(left, (int) right); + } - @Specialization(guards = "left <= asDouble(right)") - protected RDoubleSequence colonAscending(double left, int right) { - rightNA.enable(right); - naCheck(RRuntime.isNAorNaN(left) || rightNA.check(right)); - return RDataFactory.createAscendingRange(left, right); - } + @Specialization(guards = "asDouble(left) > right") + protected RIntSequence colonDescending(int left, double right) { + leftNA.enable(left); + naCheck(leftNA.check(left) || RRuntime.isNAorNaN(right)); + return RDataFactory.createDescendingRange(left, (int) right); + } - @Specialization(guards = "left > asDouble(right)") - protected RDoubleSequence colonDescending(double left, int right) { - rightNA.enable(right); - naCheck(RRuntime.isNAorNaN(left) || rightNA.check(right)); - return RDataFactory.createDescendingRange(left, right); - } + @Specialization(guards = "left <= asDouble(right)") + protected RDoubleSequence colonAscending(double left, int right) { + rightNA.enable(right); + naCheck(RRuntime.isNAorNaN(left) || rightNA.check(right)); + return RDataFactory.createAscendingRange(left, right); + } - @Specialization(guards = "left <= right") - protected RDoubleSequence colonAscending(double left, double right) { - naCheck(RRuntime.isNAorNaN(left) || RRuntime.isNAorNaN(right)); - return RDataFactory.createAscendingRange(left, right); - } + @Specialization(guards = "left > asDouble(right)") + protected RDoubleSequence colonDescending(double left, int right) { + rightNA.enable(right); + naCheck(RRuntime.isNAorNaN(left) || rightNA.check(right)); + return RDataFactory.createDescendingRange(left, right); + } - @Specialization(guards = "left > right") - protected RDoubleSequence colonDescending(double left, double right) { - naCheck(RRuntime.isNAorNaN(left) || RRuntime.isNAorNaN(right)); - return RDataFactory.createDescendingRange(left, right); - } + @Specialization(guards = "left <= right") + protected RDoubleSequence colonAscending(double left, double right) { + naCheck(RRuntime.isNAorNaN(left) || RRuntime.isNAorNaN(right)); + return RDataFactory.createAscendingRange(left, right); + } - protected static double asDouble(int intValue) { - return intValue; + @Specialization(guards = "left > right") + protected RDoubleSequence colonDescending(double left, double right) { + naCheck(RRuntime.isNAorNaN(left) || RRuntime.isNAorNaN(right)); + return RDataFactory.createDescendingRange(left, right); + } } abstract static class ColonCastNode extends CastNode { 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 812b2b7ebc0eb1ca2fd8f8808434ac585010357c..09f63d4ef28b36e3b1e0926fcbc68c2eaec598ea 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 @@ -37,6 +37,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; 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.dsl.Cached; import com.oracle.truffle.api.dsl.NodeChild; @@ -44,6 +45,7 @@ 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.builtin.base.CombineNodeGen.CombineInputCastNodeGen; import com.oracle.truffle.r.nodes.unary.CastComplexNodeGen; @@ -55,7 +57,6 @@ import com.oracle.truffle.r.nodes.unary.CastNode; import com.oracle.truffle.r.nodes.unary.CastRawNodeGen; 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.PrecedenceNode; import com.oracle.truffle.r.nodes.unary.PrecedenceNodeGen; import com.oracle.truffle.r.runtime.ArgumentsSignature; @@ -86,10 +87,19 @@ public abstract class Combine extends RBuiltinNode { protected static final int COMBINE_CACHED_LIMIT = PrecedenceNode.NUMBER_OF_PRECEDENCES; + private static final int MAX_PROFILES = 4; + @Child private PrecedenceNode precedenceNode = PrecedenceNodeGen.create(); @Child private CombineInputCast inputCast = CombineInputCastNodeGen.create(null); @Child private CastToVectorNode castVector; + private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + private final BranchProfile naBranch = BranchProfile.create(); + private final NACheck naCheck = NACheck.create(); + 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]; public abstract Object executeCombine(Object value); @@ -107,9 +117,7 @@ public abstract class Combine extends RBuiltinNode { @Cached("args.getSignature()") ArgumentsSignature cachedSignature, // @Cached("precedence( args, cachedSignature.getLength())") int cachedPrecedence, // @Cached("createCast(cachedPrecedence)") CastNode cast, // - @Cached("create()") BranchProfile naBranch, // @Cached("create()") BranchProfile naNameBranch, // - @Cached("create()") NACheck naCheck, // @Cached("create()") NACheck naNameCheck, // @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile) { CompilerAsserts.partialEvaluationConstant(cachedSignature); @@ -121,31 +129,33 @@ public abstract class Combine extends RBuiltinNode { // perform all the casts Object[] elements = new Object[cachedSignature.getLength()]; - int size = prepareElements(args.getArguments(), cachedSignature, cast, cachedPrecedence, elements); + int size = prepareElements(args.getArguments(), cast, cachedPrecedence, elements); // prepare the names (if there are any) - RStringVector namesVector = hasNamesProfile.profile(hasNames(elements)) ? foldNames(naNameBranch, naNameCheck, elements, size) : null; + boolean signatureHasNames = signatureHasNames(cachedSignature); + CompilerAsserts.partialEvaluationConstant(signatureHasNames); + RStringVector namesVector = hasNamesProfile.profile(signatureHasNames || hasNames(elements)) ? foldNames(naNameBranch, naNameCheck, elements, size, cachedSignature) : null; // get the actual contents of the result - RVector result = foldContents(cachedPrecedence, naBranch, naCheck, elements, size, namesVector); + RVector<?> result = foldContents(cachedPrecedence, elements, size, namesVector); RNode.reportWork(this, size); - if (cachedPrecedence == EXPRESSION_PRECEDENCE) { - return RDataFactory.createExpression((RList) result); - } else { - return result; - } + return result; } @ExplodeLoop - private int prepareElements(Object[] args, ArgumentsSignature signature, CastNode cast, int precedence, Object[] elements) { - boolean signatureHasNames = signatureHasNames(signature); - CompilerAsserts.partialEvaluationConstant(signatureHasNames); - + 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, signature, i, precedence, signatureHasNames); + 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); + } elements[i] = element; size += getElementSize(element); } @@ -165,7 +175,11 @@ public abstract class Combine extends RBuiltinNode { @ExplodeLoop private boolean hasNames(Object[] elements) { - for (Object element : elements) { + for (int i = 0; i < elements.length; i++) { + Object element = elements[i]; + if (i < argProfiles.length) { + element = argProfiles[i].profile(element); + } if (element instanceof RAbstractVector) { RAbstractVector vector = (RAbstractVector) element; if (vector.getNames(attrProfiles) != null) { @@ -177,22 +191,36 @@ public abstract class Combine extends RBuiltinNode { } @ExplodeLoop - private RStringVector foldNames(BranchProfile naNameBranch, NACheck naNameCheck, Object[] elements, int size) { + private RStringVector foldNames(BranchProfile naNameBranch, NACheck naNameCheck, Object[] elements, int size, ArgumentsSignature signature) { RStringVector result = RDataFactory.createStringVector(new String[size], true); result.incRefCount(); int pos = 0; - for (Object element : elements) { - pos += processNamesElement(naNameBranch, naNameCheck, result, pos, element); + for (int i = 0; i < elements.length; i++) { + Object element = elements[i]; + if (i < argProfiles.length) { + element = argProfiles[i].profile(element); + } + pos += processNamesElement(naNameBranch, naNameCheck, result, pos, element, i, signature); } return result; } - private int processNamesElement(BranchProfile naNameBranch, NACheck naNameCheck, RStringVector result, int pos, Object element) { + private int processNamesElement(BranchProfile naNameBranch, NACheck naNameCheck, RStringVector result, int pos, Object element, int index, ArgumentsSignature signature) { + String signatureName = signature.getName(index); if (element instanceof RAbstractVector) { RAbstractVector v = (RAbstractVector) element; + int length = v.getLength(); + RStringVector newNames = v.getNames(attrProfiles); - if (newNames != null) { - for (int i1 = 0; i1 < newNames.getLength(); i1++) { + if (signatureName != null && length > 0) { + if (fastNamesMerge.profile(length == 1 && newNames == null)) { + newNames = RDataFactory.createStringVector(new String[]{signatureName}, true); + } else { + newNames = RDataFactory.createStringVector(mergeNamesSlow(length, signatureName, newNames), true); + } + } + if (hasNewNamesProfile.profile(newNames != null)) { + for (int i1 = 0; i1 < length; i1++) { result.transferElementSameType(pos + i1, newNames, i1); } if (!newNames.isComplete()) { @@ -200,7 +228,7 @@ public abstract class Combine extends RBuiltinNode { result.setComplete(false); } } else { - for (int i1 = 0; i1 < v.getLength(); i1++) { + for (int i1 = 0; i1 < length; i1++) { result.updateDataAt(pos + i1, RRuntime.NAMES_ATTR_EMPTY_VALUE, naNameCheck); } } @@ -209,23 +237,24 @@ public abstract class Combine extends RBuiltinNode { // nothing to do - NULL elements are skipped return 0; } else { - result.updateDataAt(pos, RRuntime.NAMES_ATTR_EMPTY_VALUE, naNameCheck); + String name = signatureName != null ? signatureName : RRuntime.NAMES_ATTR_EMPTY_VALUE; + result.updateDataAt(pos, name, naNameCheck); return 1; } } @ExplodeLoop - private static RVector foldContents(int cachedPrecedence, BranchProfile naBranch, NACheck naCheck, Object[] elements, int size, RStringVector namesVector) { - RVector result = createResultVector(cachedPrecedence, size, namesVector); + private RVector<?> foldContents(int cachedPrecedence, Object[] elements, int size, RStringVector namesVector) { + RVector<?> result = createResultVector(cachedPrecedence, size, namesVector); int pos = 0; for (Object element : elements) { - pos += processContentElement(naBranch, naCheck, result, pos, element); + pos += processContentElement(result, pos, element); } return result; } - private static int processContentElement(BranchProfile naBranch, NACheck naCheck, RVector result, int pos, Object element) { - if (element instanceof RAbstractVector) { + private int processContentElement(RVector<?> result, int pos, Object element) { + if (isAbstractVectorProfile.profile(element instanceof RAbstractVector)) { RAbstractVector v = (RAbstractVector) element; for (int i = 0; i < v.getLength(); i++) { result.transferElementSameType(pos + i, v, i); @@ -254,12 +283,10 @@ public abstract class Combine extends RBuiltinNode { protected Object combine(RArgsValuesAndNames args, // @Cached("precedence(args, args.getLength())") int cachedPrecedence, // @Cached("createCast(cachedPrecedence)") CastNode cast, // - @Cached("create()") BranchProfile naBranch, // @Cached("create()") BranchProfile naNameBranch, // - @Cached("create()") NACheck naCheck, // @Cached("create()") NACheck naNameCheck, // @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile) { - return combineCached(args, args.getSignature(), cachedPrecedence, cast, naBranch, naNameBranch, naCheck, naNameCheck, hasNamesProfile); + return combineCached(args, args.getSignature(), cachedPrecedence, cast, naNameBranch, naNameCheck, hasNamesProfile); } @Specialization(guards = "!isArguments(args)") @@ -267,39 +294,11 @@ public abstract class Combine extends RBuiltinNode { return combine.executeCombine(new RArgsValuesAndNames(new Object[]{args}, EMPTY_SIGNATURE)); } - private Object readAndCast(CastNode castNode, Object[] values, ArgumentsSignature signature, int index, int precedence, boolean hasNames) { - Object value = inputCast.execute(values[index]); - if (hasNames) { - value = namesMerge(castVector(value), signature.getName(index)); - } + 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); } - private RAbstractVector namesMerge(RAbstractVector vector, String name) { - RStringVector orgNamesObject = vector.getNames(attrProfiles); - if (name == null) { - return vector; - } - if (vector.getLength() == 0) { - return vector; - } - return mergeNamesSlow(vector, name, orgNamesObject); - } - - private RAbstractVector castVector(Object value) { - if (castVector == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castVector = insert(CastToVectorNodeGen.create(false)); - } - RVector resultVector = ((RAbstractVector) castVector.execute(value)).materialize(); - // need to copy if vector is shared in case the same variable is used in combine, e.g. : - // x <- 1:2 ; names(x) <- c("A",NA) ; c(x,test=x) - if (resultVector.isShared()) { - resultVector = resultVector.copy(); - } - return resultVector; - } - protected int precedence(RArgsValuesAndNames args) { int precedence = NO_PRECEDENCE; Object[] array = args.getArguments(); @@ -327,7 +326,7 @@ public abstract class Combine extends RBuiltinNode { return CombineNodeGen.create(null); } - private static RVector createResultVector(int precedence, int size, RStringVector names) { + private static RVector<?> createResultVector(int precedence, int size, RStringVector names) { switch (precedence) { case COMPLEX_PRECEDENCE: return RDataFactory.createComplexVector(new double[size * 2], true, names); @@ -342,6 +341,7 @@ 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); case LIST_PRECEDENCE: return RDataFactory.createList(new Object[size], names); case NO_PRECEDENCE: @@ -362,7 +362,7 @@ public abstract class Combine extends RBuiltinNode { case LOGICAL_PRECEDENCE: return CastLogicalNodeGen.create(true, false, false); case STRING_PRECEDENCE: - return CastStringNodeGen.create(false, true, false, false); + return CastStringNodeGen.create(true, false, false); case RAW_PRECEDENCE: return CastRawNodeGen.create(true, false, false); case EXPRESSION_PRECEDENCE: @@ -376,37 +376,30 @@ public abstract class Combine extends RBuiltinNode { } @TruffleBoundary - private static RAbstractVector mergeNamesSlow(RAbstractVector vector, String name, RStringVector orgNames) { - /* - * TODO (chumer) we should reuse some node for this to concat a RStringVector with a String. - */ - RVector v = vector.materialize(); - RStringVector newNames; + private static String[] mergeNamesSlow(int length, String name, RStringVector orgNames) { + String[] names = new String[length]; if (orgNames == null) { assert (name != null); assert (!name.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE)); - if (v.getLength() == 1) { + if (length == 1) { // single value - just use the name - newNames = RDataFactory.createStringVector(new String[]{name}, true); + names[0] = name; } else { // multiple values - prepend name to the index of a given value - String[] names = new String[v.getLength()]; for (int i = 0; i < names.length; i++) { names[i] = name + (i + 1); } - newNames = RDataFactory.createStringVector(names, true); + return names; } } else { - if (vector.getLength() == 1) { - // single value - // prepend name to the original name + if (length == 1) { + // single value - prepend name to the original name assert (!name.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE)); String orgName = orgNames.getDataAt(0); - newNames = RDataFactory.createStringVector(new String[]{orgName.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE) ? name : name + "." + orgName}, true); + names[0] = orgName.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE) ? name : name + "." + orgName; } else { // multiple values - prepend name to the index of a given value or to the original // name - String[] names = new String[v.getLength()]; for (int i = 0; i < names.length; i++) { if (name == null) { names[i] = orgNames.getDataAt(i); @@ -416,11 +409,9 @@ public abstract class Combine extends RBuiltinNode { names[i] = orgName.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE) ? name + (i + 1) : name + "." + orgName; } } - newNames = RDataFactory.createStringVector(names, true); } } - v.setNames(newNames); - return v; + return names; } @NodeChild @@ -443,8 +434,8 @@ public abstract class Combine extends RBuiltinNode { protected RAbstractVector noCopy(RAbstractVector vector, // @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile, // @Cached("createBinaryProfile()") ConditionProfile hasDimNamesProfile) { - RVector materialized = vector.materialize(); - RVector result = materialized.copyDropAttributes(); + RVector<?> materialized = vector.materialize(); + RVector<?> result = materialized.copyDropAttributes(); RStringVector vecNames = materialized.getInternalNames(); if (hasNamesProfile.profile(vecNames != null)) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompilePKGS.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompilePKGS.java index 6850faf77ca56ca4492c741c59b86d14138e03fd..c8839005d1ad0e8282a8843bd7b3d63f38c5e6bd 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompilePKGS.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompilePKGS.java @@ -26,6 +26,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -35,6 +36,11 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "compilePKGS", kind = INTERNAL, parameterNames = "enable", behavior = COMPLEX) public abstract class CompilePKGS extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("enable").asIntegerVector().findFirst(0); + } + @Specialization protected byte compilePKGS(@SuppressWarnings("unused") int enable) { return 0; 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 761897f79d0795cfbe701b0f57891553f3de442f..a18522b37689d92276fc10e58cf79fae4ef4fcd0 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 @@ -22,7 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.defaultValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -45,8 +45,8 @@ public abstract class Complex extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { casts.arg("length.out").asIntegerVector().findFirst(Message.INVALID_LENGTH); - casts.arg("real").map(defaultValue(RDataFactory.createEmptyDoubleVector())).asDoubleVector(); - casts.arg("imaginary").map(defaultValue(RDataFactory.createEmptyDoubleVector())).asDoubleVector(); + casts.arg("real").mapNull(emptyDoubleVector()).asDoubleVector(); + casts.arg("imaginary").mapNull(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 b4b560584bdae56422dd18f0ed0ea4f4e13a089e..3957c5a02abfa8b64f6d1b8adc046841f4d07523 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 @@ -11,6 +11,9 @@ */ 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.size; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.runtime.RErrorHandling.getHandlerStack; import static com.oracle.truffle.r.runtime.RVisibility.OFF; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; @@ -18,7 +21,6 @@ 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.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; @@ -27,7 +29,6 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RErrorHandling; 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.RList; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @@ -52,27 +53,29 @@ public class ConditionFunctions { @RBuiltin(name = ".addCondHands", visibility = OFF, kind = INTERNAL, parameterNames = {"classes", "handlers", "parentenv", "target", "calling"}, behavior = COMPLEX) public abstract static class AddCondHands extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("classes").allowNull().mustBe(stringValue()).asStringVector(); + casts.arg("handlers").allowNull().mustBe(instanceOf(RList.class)); + casts.arg("calling").asLogicalVector().findFirst(); + } @SuppressWarnings("unused") @Specialization(guards = "isRNull(classes) || isRNull(handlers)") @TruffleBoundary protected Object addCondHands(Object classes, Object handlers, Object parentEnv, Object target, byte calling) { - RContext.getInstance().setVisible(false); return getHandlerStack(); } - @Specialization(guards = "classes.getLength() == handlers.getLength()") + @Specialization @TruffleBoundary protected Object addCondHands(RAbstractStringVector classes, RList handlers, REnvironment parentEnv, Object target, byte calling) { - RContext.getInstance().setVisible(false); + if (classes.getLength() != handlers.getLength()) { + throw RError.error(this, RError.Message.BAD_HANDLER_DATA); + } return RErrorHandling.createHandlers(classes, handlers, parentEnv, target, calling); } - @SuppressWarnings("unused") - @Fallback - protected Object fallback(Object classesObj, Object handlersObj, Object parentEnv, Object target, byte calling) { - throw RError.error(this, RError.Message.BAD_HANDLER_DATA); - } } @RBuiltin(name = ".resetCondHands", visibility = OFF, kind = INTERNAL, parameterNames = {"stack"}, behavior = COMPLEX) @@ -80,41 +83,45 @@ public class ConditionFunctions { @SuppressWarnings("unused") @Specialization protected RNull resetCondHands(Object stack) { - RContext.getInstance().setVisible(false); // TODO throw RInternalError.unimplemented(); } } public abstract static class RestartAdapter extends RBuiltinNode { - public static boolean lengthok(Object restart) { - return (restart instanceof RList) && ((RList) restart).getLength() >= 2; + protected void checkLength(RList restart) { + if (restart.getLength() < 2) { + throw RError.error(this, RError.Message.BAD_RESTART); + } } - protected RError badRestart() throws RError { - throw RError.error(this, RError.Message.BAD_RESTART); + protected void restart(CastBuilder 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 { + @Override + public void createCasts(CastBuilder casts) { + restart(casts); + } + @Specialization protected Object addRestart(RList restart) { + checkLength(restart); RErrorHandling.addRestart(restart); return RNull.instance; } - @Specialization(guards = "lengthok(restart)") - protected Object addRestart(@SuppressWarnings("unused") Object restart) { - throw badRestart(); - } } @RBuiltin(name = ".getRestart", kind = INTERNAL, parameterNames = "restart", behavior = COMPLEX) public abstract static class GetRestart extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(0); + casts.arg("restart").asIntegerVector().findFirst(); } @Specialization @@ -126,8 +133,15 @@ public class ConditionFunctions { @RBuiltin(name = ".invokeRestart", kind = INTERNAL, parameterNames = {"restart", "args"}, behavior = COMPLEX) public abstract static class InvokeRestart extends RestartAdapter { - @Specialization(guards = "lengthok(restart)") + @Override + public void createCasts(CastBuilder casts) { + restart(casts); + } + + @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 { @@ -135,11 +149,6 @@ public class ConditionFunctions { } } - @SuppressWarnings("unused") - @Fallback - protected Object invokeRestart(Object restart, Object args) { - throw badRestart(); - } } @RBuiltin(name = ".signalCondition", kind = INTERNAL, parameterNames = {"condition", "msg", "call"}, behavior = COMPLEX) @@ -161,28 +170,42 @@ public class ConditionFunctions { @RBuiltin(name = "seterrmessage", visibility = OFF, kind = INTERNAL, parameterNames = "msg", behavior = COMPLEX) public abstract static class Seterrmessage extends RBuiltinNode { + @Override + public void createCasts(CastBuilder casts) { + casts.arg("msg").defaultError(RError.Message.ERR_MSG_MUST_BE_STRING).mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst(); + } + @Specialization - protected RNull seterrmessage(RAbstractStringVector msg) { - RContext.getInstance().setVisible(false); - RErrorHandling.seterrmessage(msg.getDataAt(0)); + protected RNull seterrmessage(String msg) { + RErrorHandling.seterrmessage(msg); return RNull.instance; } } @RBuiltin(name = ".dfltWarn", kind = INTERNAL, parameterNames = {"message", "call"}, behavior = COMPLEX) public abstract static class DfltWarn extends RBuiltinNode { + @Override + public void createCasts(CastBuilder casts) { + casts.arg("message").defaultError(RError.Message.ERR_MSG_BAD).mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst(); + } + @Specialization - protected RNull dfltWarn(RAbstractStringVector msg, Object call) { - RErrorHandling.dfltWarn(msg.getDataAt(0), call); + protected RNull dfltWarn(String msg, Object call) { + RErrorHandling.dfltWarn(msg, call); return RNull.instance; } } @RBuiltin(name = ".dfltStop", kind = INTERNAL, parameterNames = {"message", "call"}, behavior = COMPLEX) public abstract static class DfltStop extends RBuiltinNode { + @Override + public void createCasts(CastBuilder casts) { + casts.arg("message").defaultError(RError.Message.ERR_MSG_BAD).mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst(); + } + @Specialization - protected Object dfltStop(RAbstractStringVector message, Object call) { - RErrorHandling.dfltStop(message.getDataAt(0), call); + protected Object dfltStop(String message, Object call) { + RErrorHandling.dfltStop(message, call); return RNull.instance; } } @@ -192,7 +215,6 @@ public class ConditionFunctions { @Specialization @TruffleBoundary protected RNull printDeferredWarnings() { - RContext.getInstance().setVisible(false); RErrorHandling.printDeferredWarnings(); return RNull.instance; } 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 4a350001e6212c0f0f9d45643a09a097ad44fc13..e28bed67c6d25c43195abd95d507df229cf9e41a 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 @@ -22,11 +22,15 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.equalTo; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +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.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.nodes.builtin.CastBuilder.Predef.trueValue; -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.IO; import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE; @@ -48,12 +52,12 @@ import java.util.zip.ZipException; 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.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.ConnectionFunctionsFactory.WriteDataNodeGen; +import com.oracle.truffle.r.nodes.builtin.casts.fluent.HeadPhaseBuilder; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; @@ -70,9 +74,9 @@ 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.RExpression; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RLogical; import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRaw; @@ -125,20 +129,51 @@ public abstract class ConnectionFunctions { } } - @RBuiltin(name = "file", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding", "raw"}, behavior = IO) - public abstract static class File extends RBuiltinNode { - - @Override - protected void createCasts(CastBuilder casts) { + private static final class Casts { + private static void description(CastBuilder casts) { casts.arg("description").mustBe(stringValue()).asStringVector().shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST_1, "description").findFirst().notNA(); + } + + private static HeadPhaseBuilder<String> open(CastBuilder casts) { + return casts.arg("open").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().notNA(); + } + + private static void encoding(CastBuilder casts) { + casts.arg("encoding").asStringVector().mustBe(singleElement()).findFirst(); + } - casts.arg("open").mustBe(stringValue()).asStringVector().findFirst().notNA(); + private static void raw(CastBuilder casts) { + casts.arg("raw").asLogicalVector().findFirst().notNA().map(toBoolean()); + } - casts.arg("blocking").asLogicalVector().findFirst().map(toBoolean()).mustBe(trueValue(), RError.Message.NYI, "non-blocking mode not supported"); + private static void blocking(CastBuilder casts) { + casts.arg("blocking").asLogicalVector().findFirst().notNA().map(toBoolean()); + } - casts.arg("encoding").asStringVector().findFirst(); + private static void connection(CastBuilder casts) { + casts.arg("con").mustBe(instanceOf(RConnection.class)); + } + + private static void nchars(CastBuilder casts) { + casts.arg("nchars").asIntegerVector().mustBe(notEmpty()); + } - casts.arg("raw").asLogicalVector().findFirst().map(toBoolean()); + private static void useBytes(CastBuilder casts) { + casts.arg("useBytes").asLogicalVector().findFirst().notNA().map(toBoolean()); + } + + } + + @RBuiltin(name = "file", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding", "raw"}, behavior = IO) + public abstract static class File extends RBuiltinNode { + + @Override + protected void createCasts(CastBuilder casts) { + Casts.description(casts); + Casts.open(casts); + casts.arg("blocking").asLogicalVector().findFirst().mustBe(logicalTrue(), RError.Message.NYI, "non-blocking mode not supported").map(toBoolean()); + Casts.encoding(casts); + Casts.raw(casts); } @Specialization @@ -167,11 +202,6 @@ public abstract class ConnectionFunctions { } } - @SuppressWarnings("unused") - @Fallback - protected Object file(Object description, Object open, Object blocking, Object encoding, Object raw) { - throw RError.error(this, RError.Message.INVALID_UNNAMED_ARGUMENTS); - } } /** @@ -181,12 +211,20 @@ public abstract class ConnectionFunctions { */ @RBuiltin(name = "gzfile", kind = INTERNAL, parameterNames = {"description", "open", "encoding", "compression"}, behavior = IO) public abstract static class GZFile extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.description(casts); + Casts.open(casts); + Casts.encoding(casts); + casts.arg("compression").asIntegerVector().findFirst().notNA().mustBe(gte(0).and(lte(9))); + } + @Specialization @TruffleBoundary @SuppressWarnings("unused") - protected Object gzFile(RAbstractStringVector description, RAbstractStringVector open, RAbstractStringVector encoding, double compression) { + protected Object gzFile(RAbstractStringVector description, String open, RAbstractStringVector encoding, int compression) { try { - return new GZIPRConnection(description.getDataAt(0), open.getDataAt(0)); + return new GZIPRConnection(description.getDataAt(0), open); } catch (ZipException ex) { // wasn't a gzip file, try uncompressed text try { @@ -205,39 +243,65 @@ public abstract class ConnectionFunctions { } } - @RBuiltin(name = "textConnection", kind = INTERNAL, parameterNames = {"nm", "object", "open", "env", "type"}, behavior = IO) + @RBuiltin(name = "textConnection", kind = INTERNAL, parameterNames = {"description", "text", "open", "env", "encoding"}, behavior = IO) public abstract static class TextConnection extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.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()); + Casts.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; + } + } + @Specialization @TruffleBoundary - protected Object textConnection(RAbstractStringVector nm, RAbstractStringVector object, RAbstractStringVector open, REnvironment env, @SuppressWarnings("unused") RAbstractIntVector encoding) { - if (nm.getLength() != 1) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "description"); + protected Object 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); + } } - // TODO more error checking as per GnuR try { - return new TextRConnection(nm.getDataAt(0), object, env, open.getDataAt(0)); + return new TextRConnection(description, object, env, open); } catch (IOException ex) { throw RInternalError.shouldNotReachHere(); } } - @SuppressWarnings("unused") - @Fallback - protected Object textConnection(Object nm, Object object, Object open, Object env, Object encoding) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); - } } @RBuiltin(name = "textConnectionValue", kind = INTERNAL, parameterNames = {"con"}, behavior = IO) public abstract static class TextConnectionValue extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("con").mustBe(instanceOf(TextRConnection.class), RError.Message.NOT_A_TEXT_CONNECTION); + } + @Specialization @TruffleBoundary - protected Object textConnection(RConnection conn) { - if (conn instanceof TextRConnection) { - return RDataFactory.createStringVector(((TextRConnection) conn).getValue(), RDataFactory.COMPLETE_VECTOR); - } else { - throw RError.error(this, RError.Message.NOT_A_TEXT_CONNECTION); - } + protected Object textConnection(TextRConnection conn) { + return RDataFactory.createStringVector(conn.getValue(), RDataFactory.COMPLETE_VECTOR); } } @@ -246,22 +310,23 @@ public abstract class ConnectionFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1); - casts.toInteger(6); + 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.open(casts); + Casts.blocking(casts); + casts.arg("timeout").asIntegerVector().findFirst(); } @Specialization @TruffleBoundary - protected Object socketConnection(RAbstractStringVector host, RAbstractIntVector portVec, byte server, byte blocking, RAbstractStringVector open, - @SuppressWarnings("unused") RAbstractStringVector encoding, RAbstractIntVector timeoutVec) { - int port = portVec.getDataAt(0); - String modeString = open.getDataAt(0); - int timeout = timeoutVec.getDataAt(0); + protected Object socketConnection(String host, int port, boolean server, boolean blocking, String open, + @SuppressWarnings("unused") RAbstractStringVector encoding, int timeout) { try { - if (RRuntime.fromLogical(server)) { - return new RSocketConnection(modeString, true, host.getDataAt(0), port, RRuntime.fromLogical(blocking), timeout); + if (server) { + return new RSocketConnection(open, true, host, port, blocking, timeout); } else { - return new RSocketConnection(modeString, false, host.getDataAt(0), port, RRuntime.fromLogical(blocking), timeout); + return new RSocketConnection(open, false, host, port, blocking, timeout); } } catch (IOException ex) { throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION); @@ -271,11 +336,20 @@ public abstract class ConnectionFunctions { @RBuiltin(name = "url", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding"}, behavior = IO) public abstract static class URLConnection extends RBuiltinNode { + + @Override + protected void createCasts(CastBuilder casts) { + Casts.description(casts); + Casts.open(casts); + Casts.blocking(casts); + Casts.encoding(casts); + } + @Specialization @TruffleBoundary - protected Object urlConnection(RAbstractStringVector url, RAbstractStringVector open, @SuppressWarnings("unused") byte blocking, @SuppressWarnings("unused") RAbstractStringVector encoding) { + protected Object urlConnection(String url, String open, @SuppressWarnings("unused") boolean blocking, @SuppressWarnings("unused") String encoding) { try { - return new URLRConnection(url.getDataAt(0), open.getDataAt(0)); + return new URLRConnection(url, open); } catch (MalformedURLException ex) { throw RError.error(this, RError.Message.UNSUPPORTED_URL_SCHEME); } catch (IOException ex) { @@ -324,11 +398,18 @@ public abstract class ConnectionFunctions { } @RBuiltin(name = "open", visibility = OFF, kind = INTERNAL, parameterNames = {"con", "open", "blocking"}, behavior = IO) - public abstract static class Open extends CheckIsConnAdapter { + public abstract static class Open extends RBuiltinNode { + + @Override + protected void createCasts(CastBuilder casts) { + Casts.connection(casts); + Casts.open(casts); + Casts.blocking(casts); + } + @Specialization @TruffleBoundary - protected Object open(RConnection con, RAbstractStringVector open, @SuppressWarnings("unused") byte blocking) { - RContext.getInstance().setVisible(false); + protected Object open(RConnection con, String open, @SuppressWarnings("unused") boolean blocking) { try { BaseRConnection baseConn = getBaseConnection(con); if (baseConn.isClosed()) { @@ -338,30 +419,29 @@ public abstract class ConnectionFunctions { RError.warning(this, RError.Message.ALREADY_OPEN_CONNECTION); return RNull.instance; } - baseConn.open(open.getDataAt(0)); + baseConn.open(open); } catch (IOException ex) { throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); } return RNull.instance; } - @SuppressWarnings("unused") - @Fallback - @TruffleBoundary - protected Object open(Object con, Object open, Object blocking) { - checkIsConnection(con); - throw RError.error(this, RError.Message.INVALID_ARG_TYPE); - } } @RBuiltin(name = "isOpen", kind = INTERNAL, parameterNames = {"con", "rw"}, behavior = IO) - public abstract static class IsOpen extends CheckIsConnAdapter { + public abstract static class IsOpen extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.connection(casts); + casts.arg("rw").asIntegerVector().findFirst(); + } + @Specialization @TruffleBoundary - protected RLogicalVector isOpen(RConnection con, RAbstractIntVector rw) { + protected RLogicalVector isOpen(RConnection con, int rw) { BaseRConnection baseCon = getBaseConnection(con); boolean result = baseCon.isOpen(); - switch (rw.getDataAt(0)) { + switch (rw) { case 0: break; case 1: @@ -376,20 +456,19 @@ public abstract class ConnectionFunctions { return RDataFactory.createLogicalVectorFromScalar(result); } - @Fallback - @TruffleBoundary - protected Object isOpen(Object con, @SuppressWarnings("unused") Object rw) { - checkIsConnection(con); - throw RError.error(this, RError.Message.INVALID_ARG_TYPE); - } } @RBuiltin(name = "close", visibility = OFF, kind = INTERNAL, parameterNames = {"con", "type"}, behavior = IO) - public abstract static class Close extends CheckIsConnAdapter { + public abstract static class Close extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.connection(casts); + casts.arg("type").asStringVector().findFirst(); + } + @Specialization @TruffleBoundary - protected Object close(RConnection con) { - RContext.getInstance().setVisible(false); + protected Object close(RConnection con, @SuppressWarnings("unused") String type) { try { con.closeAndDestroy(); } catch (IOException ex) { @@ -398,12 +477,6 @@ public abstract class ConnectionFunctions { return RNull.instance; } - @Fallback - @TruffleBoundary - protected Object close(Object con) { - checkIsConnection(con); - throw RError.error(this, RError.Message.INVALID_ARG_TYPE); - } } /** @@ -426,18 +499,21 @@ public abstract class ConnectionFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.toLogical(2); - casts.toLogical(3); - casts.toLogical(5); + Casts.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.encoding(casts); + casts.arg("skipNul").asLogicalVector().findFirst().notNA().map(toBoolean()); } @Specialization @TruffleBoundary - protected Object readLines(RConnection con, int n, byte ok, byte warn, @SuppressWarnings("unused") String encoding, byte skipNul) { + protected Object readLines(RConnection con, int n, boolean ok, boolean warn, @SuppressWarnings("unused") String encoding, boolean skipNul) { // TODO implement all the arguments try (RConnection openConn = con.forceOpen("rt")) { - String[] lines = openConn.readLines(n, RRuntime.fromLogical(warn), RRuntime.fromLogical(skipNul)); - if (n > 0 && lines.length < n && ok == RRuntime.LOGICAL_FALSE) { + 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); } return RDataFactory.createStringVector(lines, RDataFactory.COMPLETE_VECTOR); @@ -446,42 +522,38 @@ public abstract class ConnectionFunctions { } } - @Specialization - @TruffleBoundary - protected Object readLines(RConnection con, double n, byte ok, byte warn, String encoding, byte skipNul) { - return readLines(con, (int) n, ok, warn, encoding, skipNul); - } - - @SuppressWarnings("unused") - @Fallback - protected Object readLines(Object con, Object n, Object ok, Object warn, Object encoding, Object skipNul) { - throw RError.error(this, RError.Message.INVALID_UNNAMED_ARGUMENTS); - } } @RBuiltin(name = "writeLines", visibility = OFF, kind = INTERNAL, parameterNames = {"text", "con", "sep", "useBytes"}, behavior = IO) public abstract static class WriteLines extends InternalCloseHelper { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("text").asStringVector().mustBe(instanceOf(RAbstractStringVector.class)); + Casts.connection(casts); + casts.arg("sep").asStringVector().findFirst(); + Casts.useBytes(casts); + } + @Specialization @TruffleBoundary - protected RNull writeLines(RAbstractStringVector text, RConnection con, RAbstractStringVector sep, byte useBytes) { + protected RNull writeLines(RAbstractStringVector text, RConnection con, String sep, boolean useBytes) { try (RConnection openConn = con.forceOpen("wt")) { - openConn.writeLines(text, sep.getDataAt(0), RRuntime.fromLogical(useBytes)); + openConn.writeLines(text, sep, useBytes); } catch (IOException x) { throw RError.error(this, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage()); } - RContext.getInstance().setVisible(false); return RNull.instance; } - @SuppressWarnings("unused") - @Fallback - protected RNull writeLines(Object text, Object con, Object sep, Object useBytes) { - throw RError.error(this, RError.Message.INVALID_UNNAMED_ARGUMENTS); - } } @RBuiltin(name = "flush", visibility = OFF, kind = INTERNAL, parameterNames = {"con"}, behavior = IO) public abstract static class Flush extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.connection(casts); + } + @Specialization @TruffleBoundary protected RNull flush(RConnection con) { @@ -494,101 +566,79 @@ public abstract class ConnectionFunctions { } } - @RBuiltin(name = "pushBack", visibility = OFF, kind = INTERNAL, parameterNames = {"data", "connection", "newLine", "type"}, behavior = IO) + @RBuiltin(name = "pushBack", visibility = OFF, kind = INTERNAL, parameterNames = {"data", "con", "newLine", "type"}, behavior = IO) public abstract static class PushBack extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toCharacter(0); + casts.arg("data").asStringVector().mustBe(instanceOf(RAbstractStringVector.class)); + Casts.connection(casts); + casts.arg("newLine").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("type").asIntegerVector().findFirst(); } @Specialization @TruffleBoundary - protected RNull pushBack(RAbstractStringVector data, RConnection connection, RAbstractLogicalVector newLine, @SuppressWarnings("unused") RAbstractIntVector type) { - if (newLine.getLength() == 0) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "newLine"); - } - connection.pushBack(data, newLine.getDataAt(0) == RRuntime.LOGICAL_TRUE); + protected Object pushBack(RAbstractStringVector data, RConnection connection, boolean newLine, @SuppressWarnings("unused") int type) { + connection.pushBack(data, newLine); return RNull.instance; } - @SuppressWarnings("unused") - @Specialization - @TruffleBoundary - protected Object pushBack(RAbstractStringVector data, RConnection connection, RNull newLine, RAbstractIntVector type) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "newLine"); - } - - @SuppressWarnings("unused") - @Specialization(guards = "!newLineIsLogical(newLine)") - @TruffleBoundary - protected Object pushBack(RAbstractStringVector data, RConnection connection, RAbstractVector newLine, RAbstractIntVector type) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "newLine"); - } - - @SuppressWarnings("unused") - @Fallback - @TruffleBoundary - protected Object pushBack(Object data, Object connection, Object newLine, Object encoding) { - throw RError.error(this, RError.Message.INVALID_CONNECTION); - } - - protected boolean newLineIsLogical(RAbstractVector newLine) { - return newLine.getElementClass() == RLogical.class; - } } - @RBuiltin(name = "pushBackLength", kind = INTERNAL, parameterNames = {"connection"}, behavior = IO) + @RBuiltin(name = "pushBackLength", kind = INTERNAL, parameterNames = {"con"}, behavior = IO) public abstract static class PushBackLength extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.connection(casts); + } @Specialization protected int pushBackLength(RConnection connection) { return connection.pushBackLength(); } - @Fallback - protected Object pushBacklLength(@SuppressWarnings("unused") Object connection) { - throw RError.error(this, RError.Message.INVALID_CONNECTION); - } } - @RBuiltin(name = "clearPushBack", visibility = OFF, kind = INTERNAL, parameterNames = {"connection"}, behavior = IO) + @RBuiltin(name = "clearPushBack", visibility = OFF, kind = INTERNAL, parameterNames = {"con"}, behavior = IO) public abstract static class PushBackClear extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.connection(casts); + } + @Specialization protected RNull pushBackClear(RConnection connection) { connection.pushBackClear(); return RNull.instance; } - @Fallback - protected Object pushBackClear(@SuppressWarnings("unused") Object connection) { - throw RError.error(this, RError.Message.INVALID_CONNECTION); - } } @RBuiltin(name = "readChar", kind = INTERNAL, parameterNames = {"con", "nchars", "useBytes"}, behavior = IO) public abstract static class ReadChar extends InternalCloseHelper { - @SuppressWarnings("unused") - @Specialization(guards = "ncharsEmpty(nchars)") - protected RStringVector readCharNcharsEmpty(RConnection con, RAbstractIntVector nchars, RAbstractLogicalVector useBytes) { - return RDataFactory.createEmptyStringVector(); + @Override + protected void createCasts(CastBuilder casts) { + Casts.connection(casts); + Casts.nchars(casts); + Casts.useBytes(casts); } @SuppressWarnings("unused") - @Specialization(guards = "useBytesEmpty(useBytes)") - protected RStringVector readCharUseBytesEmpty(RConnection con, RAbstractIntVector nchars, RAbstractLogicalVector useBytes) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "useBytes"); + @Specialization(guards = "ncharsEmpty(nchars)") + protected RStringVector readCharNcharsEmpty(RConnection con, RAbstractIntVector nchars, boolean useBytes) { + return RDataFactory.createEmptyStringVector(); } - @Specialization(guards = {"!ncharsEmpty(nchars)", "!useBytesEmpty(useBytes)"}) + @Specialization(guards = "!ncharsEmpty(nchars)") @TruffleBoundary - protected RStringVector readChar(RConnection con, RAbstractIntVector nchars, RAbstractLogicalVector useBytes) { + protected RStringVector readChar(RConnection con, RAbstractIntVector nchars, boolean useBytes) { try (RConnection openConn = 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.getDataAt(0) == RRuntime.LOGICAL_TRUE); + data[i] = openConn.readChar(nchars.getDataAt(i), useBytes); } return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR); } catch (IOException x) { @@ -600,16 +650,22 @@ public abstract class ConnectionFunctions { return nchars.getLength() == 0; } - boolean useBytesEmpty(RAbstractLogicalVector useBytes) { - return useBytes.getLength() == 0; - } } - @RBuiltin(name = "writeChar", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"object", "con", "nchars", "eos", "useBytes"}, behavior = IO) + @RBuiltin(name = "writeChar", visibility = OFF, kind = INTERNAL, parameterNames = {"object", "con", "nchars", "sep", "useBytes"}, behavior = IO) public abstract static class WriteChar extends InternalCloseHelper { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("object").asStringVector(); + casts.arg("con").mustBe(instanceOf(RConnection.class).or(instanceOf(RAbstractRawVector.class))); + Casts.nchars(casts); + casts.arg("sep").allowNull().mustBe(stringValue()); + Casts.useBytes(casts); + } + @TruffleBoundary @Specialization - protected RNull writeChar(RAbstractStringVector object, RConnection con, RAbstractIntVector nchars, RAbstractStringVector eos, byte useBytes) { + protected RNull writeChar(RAbstractStringVector object, RConnection con, RAbstractIntVector nchars, RAbstractStringVector sep, boolean useBytes) { try (RConnection openConn = con.forceOpen("wb")) { int length = object.getLength(); for (int i = 0; i < length; i++) { @@ -619,14 +675,20 @@ public abstract class ConnectionFunctions { if (pad > 0) { RError.warning(this, RError.Message.MORE_CHARACTERS); } - openConn.writeChar(s, pad, eos.getDataAt(i % length), RRuntime.fromLogical(useBytes)); + openConn.writeChar(s, pad, sep.getDataAt(i % length), useBytes); } } catch (IOException x) { throw RError.error(this, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage()); } - RContext.getInstance().setVisible(false); return RNull.instance; } + + @SuppressWarnings("unused") + @TruffleBoundary + @Specialization + protected RNull writeChar(RAbstractStringVector object, RConnection con, RAbstractIntVector nchars, RNull sep, boolean useBytes) { + throw RError.nyi(this, "writeChar(sep=NULL)"); + } } /** @@ -643,26 +705,43 @@ public abstract class ConnectionFunctions { return buffer.order(nb); } + private abstract static class BinRBuiltinNode extends InternalCloseHelper { + protected void n(CastBuilder casts) { + casts.arg("n").asIntegerVector().findFirst().mustBe(gte(0)); + } + + protected void size(CastBuilder casts) { + casts.arg("size").asIntegerVector().findFirst(); + } + + protected void swap(CastBuilder casts) { + casts.arg("swap").asLogicalVector().findFirst().notNA().map(toBoolean()); + } + } + @RBuiltin(name = "readBin", kind = INTERNAL, parameterNames = {"con", "what", "n", "size", "signed", "swap"}, behavior = IO) - public abstract static class ReadBin extends InternalCloseHelper { + public abstract static class ReadBin extends BinRBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(2); + // TODO con can be a RAWSXP (not implemented) + Casts.connection(casts); + casts.arg("what").asStringVector().findFirst(); + n(casts); + size(casts); + casts.arg("signed").asLogicalVector().findFirst().notNA().map(toBoolean()); + swap(casts); } @Specialization @TruffleBoundary - protected Object readBin(RConnection con, RAbstractStringVector whatVec, RAbstractIntVector nVec, @SuppressWarnings("unused") int size, @SuppressWarnings("unused") byte signedArg, - byte swapArg) { - boolean swap = RRuntime.fromLogical(swapArg); - RVector result = null; - int n = nVec.getDataAt(0); + protected Object readBin(RConnection con, String what, int n, @SuppressWarnings("unused") int size, @SuppressWarnings("unused") boolean signed, + boolean swap) { + RVector<?> result = null; try (RConnection openConn = con.forceOpen("rb")) { if (getBaseConnection(openConn).getOpenMode().isText()) { throw RError.error(this, RError.Message.ONLY_READ_BINARY_CONNECTION); } - String what = whatVec.getDataAt(0); switch (what) { case "int": case "integer": @@ -865,6 +944,7 @@ public abstract class ConnectionFunctions { } @Specialization + @TruffleBoundary protected ByteBuffer writeString(RAbstractStringVector object, @SuppressWarnings("unused") int size, boolean swap, @SuppressWarnings("unused") boolean useBytes) { int length = object.getLength(); byte[][] data = new byte[length][]; @@ -908,27 +988,28 @@ public abstract class ConnectionFunctions { return buffer; } - @SuppressWarnings("unused") - @Fallback - protected ByteBuffer fallback(Object value, int size, boolean swap, boolean useBytes) { - throw RError.nyi(this, "vector type"); - } } - @RBuiltin(name = "writeBin", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"object", "con", "size", "swap", "useBytes"}, behavior = IO) - public abstract static class WriteBin extends InternalCloseHelper { + @RBuiltin(name = "writeBin", visibility = OFF, kind = INTERNAL, parameterNames = {"object", "con", "size", "swap", "useBytes"}, behavior = IO) + public abstract static class WriteBin extends BinRBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.firstIntegerWithError(2, null, null); + // TODO atomic, i.e. not RList or RExpression + casts.arg("object").asVector().mustBe(instanceOf(RAbstractVector.class)); + Casts.connection(casts); + size(casts); + swap(casts); + Casts.useBytes(casts); } @TruffleBoundary @Specialization - protected Object writeBin(RAbstractVector object, RConnection con, int size, byte swapArg, byte useBytesArg, // + protected Object writeBin(RAbstractVector object, RConnection con, int size, boolean swap, boolean useBytes, // @Cached("create()") WriteDataNode writeData) { - boolean swap = RRuntime.fromLogical(swapArg); - boolean useBytes = RRuntime.fromLogical(useBytesArg); + if (object instanceof RList || object instanceof RExpression) { + throw RError.error(this, RError.Message.INVALID_ARGUMENT, "object"); + } if (object.getLength() > 0) { try (RConnection openConn = con.forceOpen("wb")) { if (getBaseConnection(openConn).isTextMode()) { @@ -941,7 +1022,6 @@ public abstract class ConnectionFunctions { throw RError.error(this, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage()); } } - RContext.getInstance().setVisible(false); return RNull.instance; } @@ -952,7 +1032,6 @@ public abstract class ConnectionFunctions { boolean useBytes = RRuntime.fromLogical(useBytesArg); ByteBuffer buffer = writeData.execute(object, size, swap, useBytes); buffer.flip(); - RContext.getInstance().setVisible(false); return RDataFactory.createRawVector(buffer.array()); } } @@ -962,7 +1041,7 @@ public abstract class ConnectionFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(0); + casts.arg("what").asIntegerVector().findFirst(); } @Specialization @@ -988,6 +1067,12 @@ public abstract class ConnectionFunctions { @RBuiltin(name = "isSeekable", kind = INTERNAL, parameterNames = "con", behavior = IO) public abstract static class IsSeekable extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.connection(casts); + + } + @Specialization @TruffleBoundary protected byte isSeekable(RConnection con) { @@ -997,12 +1082,20 @@ public abstract class ConnectionFunctions { @RBuiltin(name = "seek", kind = INTERNAL, parameterNames = {"con", "where", "origin", "rw"}, behavior = IO) public abstract static class Seek extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.connection(casts); + casts.arg("where").asDoubleVector().findFirst(); + casts.arg("origin").asIntegerVector().findFirst(); + casts.arg("rw").asIntegerVector().findFirst(); + } + @Specialization @TruffleBoundary - protected long seek(RConnection con, RAbstractDoubleVector where, RAbstractIntVector origin, RAbstractIntVector rw) { - long offset = (long) where.getDataAt(0); + protected long seek(RConnection con, double where, int origin, int rw) { + long offset = (long) where; try { - return con.seek(offset, RConnection.SeekMode.values()[origin.getDataAt(0)], RConnection.SeekRWMode.values()[rw.getDataAt(0)]); + return con.seek(offset, RConnection.SeekMode.values()[origin], RConnection.SeekRWMode.values()[rw]); } catch (IOException x) { throw RError.error(this, RError.Message.GENERIC, x.getMessage()); } 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 7cf35c43f2710d39e66e4f09fedc23335a5c4670..bd91785573149dbf784c85774719cfbb211c6064 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 @@ -41,7 +41,7 @@ public abstract class CopyDFAttr extends RBuiltinNode { @Specialization() protected RAttributable copy(RAbstractContainer in, RAbstractVector out) { - RVector res = out.materialize(); + RVector<?> res = out.materialize(); res.resetAllAttributes(false); return res.copyAttributesFrom(attrProfiles, in); } 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 177768859206b1c9efe5fd9e697239ff55fffd5c..13d45c4cab08e9efbea2a8de9ade32c5b9c8d57c 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 @@ -22,12 +22,15 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.RDoubleVector; import com.oracle.truffle.r.runtime.data.RNull; @@ -37,22 +40,20 @@ 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 { - @Child private MatMult matMult; + @Child private MatMult matMult = MatMultNodeGen.create(/* promoteDimNames: */ false, null); @Child private Transpose transpose; - private void ensureMatMult() { - if (matMult == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - matMult = insert(MatMultNodeGen.create(/* promoteDimNames: */ false, null)); - } + @Override + protected void createCasts(CastBuilder casts) { + 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())); } private Object matMult(Object op1, Object op2) { - ensureMatMult(); return matMult.executeObject(op1, op2); } - private Object transpose(Object value) { + private Object transpose(RAbstractVector value) { if (transpose == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); transpose = insert(TransposeNodeGen.create(null)); @@ -60,9 +61,8 @@ public abstract class Crossprod extends RBuiltinNode { return transpose.execute(value); } - @Specialization(guards = {"isMatrix(x)", "isMatrix(y)"}) + @Specialization(guards = {"x.isMatrix()", "y.isMatrix()"}) protected RDoubleVector crossprod(RAbstractDoubleVector x, RAbstractDoubleVector y) { - ensureMatMult(); int xRows = x.getDimensions()[0]; int xCols = x.getDimensions()[1]; int yRows = y.getDimensions()[0]; @@ -95,9 +95,8 @@ public abstract class Crossprod extends RBuiltinNode { return matMult(transpose(x), y); } - @Specialization(guards = "isMatrix(x)") - protected Object crossprodDoubleMatrix(RAbstractDoubleVector x, @SuppressWarnings("unused") RNull y) { - ensureMatMult(); + @Specialization(guards = "x.isMatrix()") + protected RDoubleVector crossprodDoubleMatrix(RAbstractDoubleVector x, @SuppressWarnings("unused") RNull y) { int xRows = x.getDimensions()[0]; int xCols = x.getDimensions()[1]; return mirror(matMult.doubleMatrixMultiply(x, x, xCols, xRows, xRows, xCols, xRows, 1, 1, xRows, true)); @@ -107,8 +106,4 @@ public abstract class Crossprod extends RBuiltinNode { protected Object crossprod(RAbstractVector x, @SuppressWarnings("unused") RNull y) { return matMult(transpose(x), x); } - - protected static boolean isMatrix(RAbstractVector v) { - return v.isMatrix(); - } } 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 b7782c6d00e951bd5cae5355e3987c012a2748dc..edf8441b58c47ee9bad392bd698d4bc1c72247d7 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 @@ -10,34 +10,33 @@ */ 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.asIntegerVector; +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.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; -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.CastBuilder; 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.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -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.RIntSequence; import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; +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.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.ops.na.NACheck; @RBuiltin(name = "cummax", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) @@ -46,7 +45,11 @@ public abstract class CumMax extends RBuiltinNode { private final NACheck na = NACheck.create(); private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); - @Child private CastDoubleNode castDouble; + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").allowNull().mustBe(complexValue().not(), RError.Message.CUMMAX_UNDEFINED_FOR_COMPLEX).mapIf(integerValue().or(logicalValue()), asIntegerVector(), + asDoubleVector()); + } @Specialization protected double cummax(double arg) { @@ -59,17 +62,8 @@ public abstract class CumMax extends RBuiltinNode { } @Specialization - protected Object cummax(String arg) { - return na.convertStringToDouble(arg); - } - - @Specialization - protected int cummax(byte arg) { - na.enable(arg); - if (na.check(arg)) { - return RRuntime.INT_NA; - } - return arg; + protected RDoubleVector cumNull(@SuppressWarnings("unused") RNull rnull) { + return RDataFactory.createEmptyDoubleVector(); } @Specialization @@ -127,40 +121,4 @@ public abstract class CumMax extends RBuiltinNode { return RDataFactory.createIntVector(cmaxV, na.neverSeenNA(), v.getNames(attrProfiles)); } - @Specialization - protected RIntVector cummax(RAbstractLogicalVector v) { - int[] cmaxV = new int[v.getLength()]; - int max = v.getDataAt(0); - cmaxV[0] = max; - na.enable(v); - int i; - for (i = 1; i < v.getLength(); i++) { - if (v.getDataAt(i) > max) { - max = v.getDataAt(i); - } - if (na.check(v.getDataAt(i))) { - break; - } - cmaxV[i] = max; - } - if (!na.neverSeenNA()) { - Arrays.fill(cmaxV, i, cmaxV.length, RRuntime.INT_NA); - } - return RDataFactory.createIntVector(cmaxV, na.neverSeenNA(), v.getNames(attrProfiles)); - } - - @Specialization - protected RDoubleVector cummax(RAbstractStringVector v) { - if (castDouble == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castDouble = insert(CastDoubleNodeGen.create(false, false, false)); - } - return cummax((RDoubleVector) castDouble.executeDouble(v)); - } - - @Specialization - @TruffleBoundary - protected RComplexVector cummax(@SuppressWarnings("unused") RAbstractComplexVector v) { - throw RError.error(this, RError.Message.CUMMAX_UNDEFINED_FOR_COMPLEX); - } } 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 2750b3179beb14df90563f66649ddee6b23699f3..a1da7b792e40c8abb45fa505b7b76c03946a281f 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 @@ -10,34 +10,33 @@ */ 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.asIntegerVector; +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.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; -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.CastBuilder; 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.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -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.RIntSequence; import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; +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.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.ops.na.NACheck; @RBuiltin(name = "cummin", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) @@ -46,7 +45,11 @@ public abstract class CumMin extends RBuiltinNode { private final NACheck na = NACheck.create(); private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); - @Child private CastDoubleNode castDouble; + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").allowNull().mustBe(complexValue().not(), RError.Message.CUMMIN_UNDEFINED_FOR_COMPLEX).mapIf(integerValue().or(logicalValue()), asIntegerVector(), + asDoubleVector()); + } @Specialization protected double cummin(double arg) { @@ -59,17 +62,8 @@ public abstract class CumMin extends RBuiltinNode { } @Specialization - protected int cummin(byte arg) { - na.enable(arg); - if (na.check(arg)) { - return RRuntime.INT_NA; - } - return arg; - } - - @Specialization - protected double cummin(String arg) { - return na.convertStringToDouble(arg); + protected RDoubleVector cumNull(@SuppressWarnings("unused") RNull rnull) { + return RDataFactory.createEmptyDoubleVector(); } @Specialization @@ -127,40 +121,4 @@ public abstract class CumMin extends RBuiltinNode { return RDataFactory.createIntVector(cminV, na.neverSeenNA(), v.getNames(attrProfiles)); } - @Specialization - protected RIntVector cummin(RAbstractLogicalVector v) { - int[] cminV = new int[v.getLength()]; - int min = v.getDataAt(0); - cminV[0] = min; - na.enable(v); - int i; - for (i = 1; i < v.getLength(); i++) { - if (v.getDataAt(i) < min) { - min = v.getDataAt(i); - } - if (na.check(v.getDataAt(i))) { - break; - } - cminV[i] = min; - } - if (!na.neverSeenNA()) { - Arrays.fill(cminV, i, cminV.length, RRuntime.INT_NA); - } - return RDataFactory.createIntVector(cminV, na.neverSeenNA(), v.getNames(attrProfiles)); - } - - @Specialization - protected RDoubleVector cummin(RAbstractStringVector v) { - if (castDouble == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castDouble = insert(CastDoubleNodeGen.create(false, false, false)); - } - return cummin((RDoubleVector) castDouble.executeDouble(v)); - } - - @Specialization - @TruffleBoundary - protected RComplexVector cummin(@SuppressWarnings("unused") RAbstractComplexVector v) { - throw RError.error(this, RError.Message.CUMMIN_UNDEFINED_FOR_COMPLEX); - } } 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 96fc9287d2681b8242bd61eea13be9be67dea076..377b8a51794a1d99c72a5750e0d856511f23d36e 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 @@ -10,6 +10,13 @@ */ 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.asIntegerVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain; +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.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; @@ -17,6 +24,7 @@ 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.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -26,11 +34,10 @@ 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; +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.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -42,6 +49,11 @@ public abstract class CumProd extends RBuiltinNode { @Child private BinaryArithmetic mul = BinaryArithmetic.MULTIPLY.create(); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").allowNull().mapIf(integerValue().or(logicalValue()), asIntegerVector(), chain(mapIf(complexValue().not(), asDoubleVector())).end()); + } + @Specialization protected int cumprod(int arg) { return arg; @@ -53,12 +65,8 @@ public abstract class CumProd extends RBuiltinNode { } @Specialization - protected int cumprod(byte arg) { - na.enable(arg); - if (na.check(arg)) { - return RRuntime.INT_NA; - } - return arg; + protected RDoubleVector cumNull(@SuppressWarnings("unused") RNull rnull) { + return RDataFactory.createEmptyDoubleVector(); } @Specialization @@ -105,47 +113,6 @@ public abstract class CumProd extends RBuiltinNode { return RDataFactory.createDoubleVector(array, !na.neverSeenNA(), arg.getNames(attrProfiles)); } - @Specialization - protected RIntVector cumprod(RAbstractLogicalVector arg) { - int[] array = new int[arg.getLength()]; - na.enable(arg); - int prev = 1; - int i; - for (i = 0; i < arg.getLength(); i++) { - if (na.check(arg.getDataAt(i))) { - break; - } - prev = mul.op(prev, arg.getDataAt(i)); - if (na.check(prev)) { - break; - } - array[i] = prev; - } - if (!na.neverSeenNA()) { - Arrays.fill(array, i, array.length, RRuntime.INT_NA); - } - return RDataFactory.createIntVector(array, !na.neverSeenNA(), arg.getNames(attrProfiles)); - } - - @Specialization - protected RDoubleVector cumprod(RAbstractStringVector arg) { - double[] array = new double[arg.getLength()]; - na.enable(arg); - double prev = 1; - int i; - for (i = 0; i < arg.getLength(); i++) { - prev = mul.op(prev, na.convertStringToDouble(arg.getDataAt(i))); - if (na.check(arg.getDataAt(i))) { - break; - } - array[i] = prev; - } - if (!na.neverSeenNA()) { - Arrays.fill(array, i, array.length, RRuntime.DOUBLE_NA); - } - return RDataFactory.createDoubleVector(array, !na.neverSeenNA(), arg.getNames(attrProfiles)); - } - @Specialization protected RComplexVector cumprod(RAbstractComplexVector arg) { double[] array = new double[arg.getLength() * 2]; 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 2195f2c9dd28e04248e240ab0598c90f01edabc6..9e259d23d2ea5fb214c683a553714afbbc22be3c 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 @@ -22,6 +22,13 @@ */ 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.asIntegerVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain; +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.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; @@ -29,6 +36,7 @@ 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.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -39,11 +47,10 @@ 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.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.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -55,6 +62,11 @@ public abstract class CumSum extends RBuiltinNode { @Child private BinaryArithmetic add = BinaryArithmetic.ADD.create(); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").allowNull().mapIf(integerValue().or(logicalValue()), asIntegerVector(), chain(mapIf(complexValue().not(), asDoubleVector())).end()); + } + @Specialization protected double cumsum(double arg) { return arg; @@ -66,12 +78,8 @@ public abstract class CumSum extends RBuiltinNode { } @Specialization - protected int cumsum(byte arg) { - na.enable(arg); - if (na.check(arg)) { - return RRuntime.INT_NA; - } - return arg; + protected RDoubleVector cumNull(@SuppressWarnings("unused") RNull rnull) { + return RDataFactory.createEmptyDoubleVector(); } @Specialization @@ -136,45 +144,6 @@ public abstract class CumSum extends RBuiltinNode { return RDataFactory.createIntVector(res, na.neverSeenNA(), arg.getNames(attrProfiles)); } - @Specialization - protected RIntVector cumsum(RAbstractLogicalVector arg) { - int[] res = new int[arg.getLength()]; - int prev = 0; - int i; - na.enable(true); - for (i = 0; i < arg.getLength(); i++) { - prev = add.op(prev, arg.getDataAt(i)); - if (na.check(arg.getDataAt(i))) { - break; - } - res[i] = prev; - } - if (!na.neverSeenNA()) { - Arrays.fill(res, i, res.length, RRuntime.INT_NA); - } - return RDataFactory.createIntVector(res, na.neverSeenNA(), arg.getNames(attrProfiles)); - } - - @Specialization - protected RDoubleVector cumsum(RAbstractStringVector arg) { - double[] res = new double[arg.getLength()]; - double prev = 0.0; - na.enable(true); - int i; - for (i = 0; i < arg.getLength(); i++) { - double value = na.convertStringToDouble(arg.getDataAt(i)); - prev = add.op(prev, value); - if (na.check(arg.getDataAt(i))) { - break; - } - res[i] = prev; - } - if (!na.neverSeenNA()) { - Arrays.fill(res, i, res.length, RRuntime.DOUBLE_NA); - } - return RDataFactory.createDoubleVector(res, na.neverSeenNA(), arg.getNames(attrProfiles)); - } - @Specialization protected RComplexVector cumsum(RAbstractComplexVector arg) { double[] res = new double[arg.getLength() * 2]; 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 0f9af5573a7f20ff75e07878e87cdb3d6a7339c4..88021a84b5f6adb5ce46ffaab13c5e7396ca1b25 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 @@ -45,7 +45,8 @@ public abstract class DPut extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.firstIntegerWithError(2, RError.Message.WRONG_LENGTH_ARG, "opts"); + casts.arg("file").mustBe(RConnection.class); + casts.arg("opts").asIntegerVector().findFirst(); } @Specialization 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 dbf4ae312339bcad43447c707c1947a08746efff..c9a3e2826bcf8d325844e894e04922fb2c9f369a 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 @@ -11,9 +11,9 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.defaultValue; +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.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; @@ -140,7 +140,7 @@ public class DatePOSIXFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.arg("x").map(defaultValue(RDataFactory.createEmptyDoubleVector())).asDoubleVector(); + casts.arg("x").mapNull(emptyDoubleVector()).asDoubleVector(); } @Specialization @@ -176,7 +176,7 @@ public class DatePOSIXFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.arg("x").map(defaultValue(RDataFactory.createEmptyDoubleVector())).asDoubleVector(true, false, false); + casts.arg("x").mapNull(emptyDoubleVector()).asDoubleVector(true, false, false); casts.arg("tz").asStringVector().findFirst(""); } @@ -333,7 +333,7 @@ public class DatePOSIXFunctions { @Override protected void createCasts(CastBuilder casts) { casts.arg("x").mustBe(RAbstractListVector.class); - casts.arg("format").mustBe(nullValue().not()).asStringVector().mustBe(notEmpty()); + casts.arg("format").asStringVector().mustBe(notEmpty()); casts.arg("usetz").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); } @@ -390,9 +390,9 @@ public class DatePOSIXFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.arg("x").map(defaultValue(RDataFactory.createEmptyStringVector())).asStringVector(); - casts.arg("format").map(defaultValue(RDataFactory.createEmptyStringVector())).asStringVector(); - casts.arg("tz").map(defaultValue(RDataFactory.createEmptyStringVector())).asStringVector(); + casts.arg("x").mapNull(emptyStringVector()).asStringVector(); + casts.arg("format").mapNull(emptyStringVector()).asStringVector(); + casts.arg("tz").mapNull(emptyStringVector()).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 b3c1e4e12ecbfda586c8a7223cb96e15c3b07c3a..a4ed591f4a180e85358173bb53b0c57a4346d00d 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 @@ -28,23 +28,24 @@ 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.TruffleBoundary; -import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.helpers.DebugHandling; 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.context.RContext; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RNull; public class DebugFunctions { - protected abstract static class ErrorAdapter extends RBuiltinNode { + protected abstract static class ErrorAndFunAdapter extends RBuiltinNode { - protected RError arg1Closure() throws RError { - throw RError.error(this, RError.Message.ARG_MUST_BE_CLOSURE); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("fun").mustBe(RFunction.class, Message.ARG_MUST_BE_CLOSURE); } protected void doDebug(RFunction fun, Object text, Object condition, boolean once) throws RError { @@ -58,14 +59,7 @@ public class DebugFunctions { } @RBuiltin(name = "debug", visibility = OFF, kind = INTERNAL, parameterNames = {"fun", "text", "condition"}, behavior = COMPLEX) - public abstract static class Debug extends ErrorAdapter { - - @SuppressWarnings("unused") - @Fallback - @TruffleBoundary - protected Object doDebug(Object fun, Object text, Object condition) { - throw arg1Closure(); - } + public abstract static class Debug extends ErrorAndFunAdapter { @Specialization @TruffleBoundary @@ -76,14 +70,7 @@ public class DebugFunctions { } @RBuiltin(name = "debugonce", visibility = OFF, kind = INTERNAL, parameterNames = {"fun", "text", "condition"}, behavior = COMPLEX) - public abstract static class DebugOnce extends ErrorAdapter { - - @SuppressWarnings("unused") - @Fallback - @TruffleBoundary - protected Object doDebug(Object fun, Object text, Object condition) { - throw arg1Closure(); - } + public abstract static class DebugOnce extends ErrorAndFunAdapter { @Specialization @TruffleBoundary @@ -95,13 +82,7 @@ public class DebugFunctions { } @RBuiltin(name = "undebug", visibility = OFF, kind = INTERNAL, parameterNames = {"fun"}, behavior = COMPLEX) - public abstract static class UnDebug extends ErrorAdapter { - - @Fallback - @TruffleBoundary - protected Object doDebug(@SuppressWarnings("unused") Object fun) { - throw arg1Closure(); - } + public abstract static class UnDebug extends ErrorAndFunAdapter { @Specialization @TruffleBoundary @@ -114,18 +95,11 @@ public class DebugFunctions { } @RBuiltin(name = "isdebugged", kind = INTERNAL, parameterNames = {"fun"}, behavior = PURE) - public abstract static class IsDebugged extends ErrorAdapter { - - @Fallback - @TruffleBoundary - protected Object doDebug(@SuppressWarnings("unused") Object fun) { - throw arg1Closure(); - } + public abstract static class IsDebugged extends ErrorAndFunAdapter { @Specialization @TruffleBoundary protected byte isDebugged(RFunction func) { - RContext.getInstance().setVisible(true); return RRuntime.asLogical(DebugHandling.isDebugged(func)); } } 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 f168a9091a6ca09a23607df8c4191f6e0b291c4b..aee8c55217c12109347334911becede38d068c4a 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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.INTERNAL; @@ -30,6 +31,7 @@ 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.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -37,7 +39,6 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RNull; 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.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.REnvironment.PutException; @@ -46,10 +47,16 @@ public abstract class DelayedAssign extends RBuiltinNode { private final BranchProfile errorProfile = BranchProfile.create(); + @Override + protected void createCasts(CastBuilder casts) { + 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)); + } + @Specialization @TruffleBoundary - protected Object doDelayedAssign(RAbstractStringVector nameVec, Object value, REnvironment evalEnv, REnvironment assignEnv) { - String name = nameVec.getDataAt(0); + protected Object doDelayedAssign(String name, Object value, REnvironment evalEnv, REnvironment assignEnv) { try { assignEnv.put(name, RDataFactory.createPromise(PromiseState.Explicit, Closure.create(RASTUtils.createNodeForValue(value)), evalEnv.getFrame())); return RNull.instance; 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 df49796ab0444b3f8b72c4c0655f816a371107b0..8fb0d1ffbe14d540b1957761085e9368f164a9dd 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 @@ -11,6 +11,7 @@ */ 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.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -24,7 +25,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.RStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; // Part of this transcribed from GnuR src/main/deparse.c @@ -33,22 +33,22 @@ public abstract class Deparse extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.firstIntegerWithError(1, null, null); - casts.toLogical(2); - casts.toInteger(3); - casts.toInteger(4); + casts.arg("width.cutoff").asIntegerVector().findFirst(0); + casts.arg("backtick").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).map(toBoolean()); + casts.arg("control").asIntegerVector().findFirst(); + casts.arg("nlines").asIntegerVector().findFirst(-1); } @Specialization @TruffleBoundary - protected RStringVector deparse(Object expr, int widthCutoffArg, RAbstractLogicalVector backtick, int control, int nlines) { + 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); widthCutoff = RDeparse.DEFAULT_Cutoff; } - String[] data = RDeparse.deparse(expr, widthCutoff, RRuntime.fromLogical(backtick.getDataAt(0)), control, nlines).split("\n"); + String[] data = RDeparse.deparse(expr, widthCutoff, backtick, control, nlines).split("\n"); return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR); } } 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 cef023b4ca96e6de59d5812421ae3ea33c665dab..b8130992c80cc11e3786415aff64f48aa678dd0d 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 @@ -12,18 +12,20 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; +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.gte0; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notIntNA; 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.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.unary.CastDoubleNode; 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; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -37,7 +39,7 @@ public abstract class Diag extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.arg("x").asVector(); + casts.arg("x").allowNull().mapIf(complexValue().not(), asDoubleVector()); casts.arg("nrow").asIntegerVector().findFirst().mustBe(notIntNA(), Message.INVALID_LARGE_NA_VALUE, "nrow").mustBe(gte0(), Message.INVALID_NEGATIVE_VALUE, "nrow"); @@ -62,6 +64,17 @@ public abstract class Diag extends RBuiltinNode { } } + @Specialization + protected Object diag(double x, int nrow, int ncol) { + int mn = (nrow < ncol) ? nrow : ncol; + + double[] data = new double[nrow * ncol]; + for (int j = 0; j < mn; j++) { + data[j * (nrow + 1)] = x; + } + return RDataFactory.createDoubleVector(data, RRuntime.isNA(x), new int[]{nrow, ncol}); + } + @Specialization protected Object diag(RAbstractComplexVector x, int nrow, int ncol) { int mn = checkX(x, nrow, ncol); @@ -77,12 +90,10 @@ public abstract class Diag extends RBuiltinNode { return RDataFactory.createComplexVector(data, x.isComplete(), new int[]{nrow, ncol}); } - @Specialization(guards = "!isRAbstractComplexVector(x)") - protected Object diag(RAbstractVector x, int nrow, int ncol, // - @Cached("create()") CastDoubleNode cast) { - int mn = checkX(x, nrow, ncol); + @Specialization + protected Object diag(RAbstractDoubleVector source, int nrow, int ncol) { + int mn = checkX(source, nrow, ncol); - RAbstractDoubleVector source = (RAbstractDoubleVector) cast.execute(x); double[] data = new double[nrow * ncol]; int nx = source.getLength(); for (int j = 0; j < mn; j++) { 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 ad8f86e42f42b15c0712c43bb854fca58d8ec9aa..17661779644a7b819009377f238888db6a8a9fde 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 @@ -41,8 +41,8 @@ public abstract class DimNames extends RBuiltinNode { private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); private final ConditionProfile nullProfile = ConditionProfile.createBinaryProfile(); - @Specialization - protected RNull getDimNames(@SuppressWarnings("unused") RNull operand) { + @Specialization(guards = "!isRAbstractContainer(operand)") + protected RNull getDimNames(@SuppressWarnings("unused") Object operand) { return RNull.instance; } 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 48de05402f1c175814fce6bba12c085977559302..a28c9d4994dbb2499cc48912a45e2c9e8b10d576 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 @@ -22,6 +22,8 @@ */ 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.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.INTERNAL; @@ -35,6 +37,7 @@ 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.FrameSlotNode; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.GetFunctionsFactory.GetNodeGen; import com.oracle.truffle.r.nodes.function.GetCallerFrameNode; @@ -42,8 +45,10 @@ import com.oracle.truffle.r.nodes.function.RCallBaseNode; import com.oracle.truffle.r.nodes.function.RCallNode; 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.RType; 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.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -52,15 +57,16 @@ 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.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.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; -// TODO Implement properly, this is a simple implementation that works when the environment doesn't matter +// TODO Implement completely, this is a simple implementation that works when the envir argument is ignored @RBuiltin(name = "do.call", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"what", "args", "envir"}, behavior = COMPLEX) public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNodeChildren { @@ -68,7 +74,6 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode @Child private GetCallerFrameNode getCallerFrame; private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); - private final BranchProfile errorProfile = BranchProfile.create(); private final BranchProfile containsRLanguageProfile = BranchProfile.create(); private final BranchProfile containsRSymbolProfile = BranchProfile.create(); @@ -76,29 +81,36 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode @Child private RCallBaseNode call = RCallNode.createExplicitCall(argsIdentifier); @Child private FrameSlotNode slot = FrameSlotNode.createTemp(argsIdentifier, true); + @Override + protected void createCasts(CastBuilder casts) { + 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("envir").mustBe(REnvironment.class, Message.MUST_BE_ENVIRON, "envir"); + } + @Specialization - protected Object doDoCall(VirtualFrame frame, Object what, RList argsAsList, REnvironment env) { - /* - * Step 1: handle the variants of "what" (could be done in extra specializations) and assign - * "func". - */ + protected Object doCall(VirtualFrame frame, String what, RList argsAsList, REnvironment env) { RFunction func; - if (what instanceof RFunction) { - func = (RFunction) what; - } else if (what instanceof String || (what instanceof RAbstractStringVector && ((RAbstractStringVector) what).getLength() == 1)) { - if (getNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - getNode = insert(GetNodeGen.create(null)); - } - func = (RFunction) getNode.execute(frame, what, env, RType.Function.getName(), true); - } else { - errorProfile.enter(); + if (getNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getNode = insert(GetNodeGen.create(null)); + } + func = (RFunction) getNode.execute(frame, what, env, RType.Function.getName(), true); + return doCall(frame, func, argsAsList, env); + } + + @Specialization + protected Object doCall(VirtualFrame frame, RStringVector what, RList argsAsList, REnvironment env) { + if (what.getLength() != 1) { throw RError.error(this, RError.Message.MUST_BE_STRING_OR_FUNCTION, "what"); } + return doCall(frame, what.getDataAt(0), argsAsList, env); + } + @Specialization + protected Object doCall(VirtualFrame frame, RFunction func, RList argsAsList, @SuppressWarnings("unused") REnvironment env) { /* - * Step 2: To re-create the illusion of a normal call, turn the values in argsAsList into - * promises. + * To re-create the illusion of a normal call, turn the values in argsAsList into promises. */ Object[] argValues = argsAsList.getDataCopy(); RStringVector n = argsAsList.getNames(attrProfiles); @@ -120,7 +132,7 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode containsRLanguageProfile.enter(); callerFrame = getCallerFrame(frame, callerFrame); RLanguage lang = (RLanguage) arg; - argValues[i] = createArgPromise(callerFrame, RASTUtils.cloneNode(lang.getRep())); + argValues[i] = createRLanguagePromise(callerFrame, lang); } else if (arg instanceof RSymbol) { containsRSymbolProfile.enter(); RSymbol symbol = (RSymbol) arg; @@ -128,7 +140,7 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode argValues[i] = REmpty.instance; } else { callerFrame = getCallerFrame(frame, callerFrame); - argValues[i] = createArgPromise(callerFrame, RASTUtils.createReadVariableNode(symbol.getName())); + argValues[i] = createLookupPromise(callerFrame, symbol); } } } @@ -141,6 +153,17 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode } } + @TruffleBoundary + private static RPromise createLookupPromise(MaterializedFrame callerFrame, RSymbol symbol) { + Closure closure = RPromise.Closure.create(RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, symbol.getName(), false).asRNode()); + return RDataFactory.createPromise(PromiseState.Supplied, closure, callerFrame); + } + + @TruffleBoundary + private static RPromise createRLanguagePromise(MaterializedFrame callerFrame, RLanguage lang) { + return RDataFactory.createPromise(PromiseState.Supplied, RPromise.Closure.create(RASTUtils.cloneNode(lang.getRep())), callerFrame); + } + private MaterializedFrame getCallerFrame(VirtualFrame frame, MaterializedFrame callerFrame) { if (getCallerFrame == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -152,9 +175,4 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode return callerFrame; } } - - @TruffleBoundary - private static RPromise createArgPromise(MaterializedFrame frame, RBaseNode rep) { - return RDataFactory.createPromise(PromiseState.Supplied, RPromise.Closure.create(rep), frame); - } } 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 92d1f7bb6c31f98d334945bba1395dc8e1fdf847..43cfb6a97d7bde5e346af117e8b0e2762f640d5d 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 @@ -25,6 +25,7 @@ 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.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; @@ -132,4 +133,9 @@ public abstract class Drop extends RBuiltinNode { return RDataFactory.createStringVector(new String[]{(String) value}, true); } } + + @Fallback + protected Object doDrop(Object x) { + return x; + } } 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 8d3e7cd3cda9aadd72f58434d70fd1a647a92876..24acef240f44bff271e3b80a8e4bcb1df53537db 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 @@ -11,25 +11,30 @@ 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.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.ConditionProfile; import com.oracle.truffle.r.nodes.binary.CastTypeNode; import com.oracle.truffle.r.nodes.binary.CastTypeNodeGen; import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.RType; 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.RNull; +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; @@ -39,8 +44,29 @@ public class DuplicatedFunctions { @Child protected CastTypeNode castTypeNode; @Child protected TypeofNode typeof; - protected boolean isIncomparable(byte incomparables) { - return incomparables == RRuntime.LOGICAL_TRUE; + private final ConditionProfile incomparable = ConditionProfile.createBinaryProfile(); + + protected void casts(CastBuilder 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(); + // 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) { @@ -56,92 +82,88 @@ public class DuplicatedFunctions { } } - @RBuiltin(name = "duplicated", kind = INTERNAL, parameterNames = {"x", "imcomparables", "fromLast", "nmax"}, behavior = PURE) + @RBuiltin(name = "duplicated", kind = INTERNAL, parameterNames = {"x", "incomparables", "fromLast", "nmax"}, behavior = PURE) public abstract static class Duplicated extends Adapter { @Override protected void createCasts(CastBuilder casts) { - casts.toLogical(2).toInteger(3); + casts(casts); + // currently not supported and not tested, but NA is a correct value (the same for empty + // vectors) whereas 0 is not (throws an error) + casts.arg("nmax").asIntegerVector().findFirst(RRuntime.INT_NA); } @TruffleBoundary - protected static RLogicalVector analyzeAndCreateResult(RAbstractContainer x, RAbstractContainer incomparables, byte fromLast) { + 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); } - @SuppressWarnings("unused") - @Specialization - protected RLogicalVector duplicated(RNull x, Object incomparables, byte fromLast, int nmax) { - return RDataFactory.createEmptyLogicalVector(); - } - @Specialization(guards = {"!isIncomparable(incomparables)", "!empty(x)"}) - protected RLogicalVector duplicatedFalseIncomparables(RAbstractVector x, @SuppressWarnings("unused") byte incomparables, byte fromLast, @SuppressWarnings("unused") int nmax) { + 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, byte incomparables, byte fromLast, @SuppressWarnings("unused") int nmax) { + protected RLogicalVector duplicatedTrueIncomparables(RAbstractVector x, RAbstractVector incomparables, byte fromLast, @SuppressWarnings("unused") int nmax) { initChildren(); RType xType = typeof.execute(x); RAbstractVector vector = (RAbstractVector) (castTypeNode.execute(incomparables, xType)); return analyzeAndCreateResult(x, vector, fromLast); } - @Specialization(guards = {"!empty(x)"}) - protected RLogicalVector duplicated(RAbstractContainer x, RAbstractContainer incomparables, byte fromLast, @SuppressWarnings("unused") int nmax) { + @SuppressWarnings("unused") + @Specialization(guards = {"notAbstractVector(incomparables)", "!empty(x)"}) + protected RLogicalVector duplicatedTrueIncomparables(RAbstractVector x, Object incomparables, byte fromLast, int nmax) { initChildren(); RType xType = typeof.execute(x); - return analyzeAndCreateResult(x, (RAbstractContainer) (castTypeNode.execute(incomparables, xType)), fromLast); + // 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()); } @SuppressWarnings("unused") @Specialization(guards = "empty(x)") - protected RLogicalVector duplicatedEmpty(RAbstractContainer x, RAbstractContainer incomparables, byte fromLast, int nmax) { - return RDataFactory.createLogicalVector(0); + protected RLogicalVector duplicatedEmpty(RAbstractVector x, Object incomparables, byte fromLast, int nmax) { + return RDataFactory.createEmptyLogicalVector(); } } - @RBuiltin(name = "anyDuplicated", kind = INTERNAL, parameterNames = {"x", "imcomparables", "fromLast"}, behavior = PURE) + @RBuiltin(name = "anyDuplicated", kind = INTERNAL, parameterNames = {"x", "incomparables", "fromLast"}, behavior = PURE) public abstract static class AnyDuplicated extends Adapter { @Override protected void createCasts(CastBuilder casts) { - casts.toLogical(2); + casts(casts); } @SuppressWarnings("unused") @Specialization(guards = {"!isIncomparable(incomparables)", "!empty(x)"}) - protected int anyDuplicatedFalseIncomparables(RAbstractVector x, byte incomparables, byte fromLast) { + 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, byte incomparables, byte fromLast) { + protected int anyDuplicatedTrueIncomparables(RAbstractVector x, RAbstractVector incomparables, byte fromLast) { initChildren(); RType xType = typeof.execute(x); - RAbstractVector vector = (RAbstractVector) (castTypeNode.execute(incomparables, xType)); - return DuplicationHelper.analyze(x, vector, true, RRuntime.fromLogical(fromLast)).getIndex(); + return DuplicationHelper.analyze(x, (RAbstractVector) (castTypeNode.execute(incomparables, xType)), true, RRuntime.fromLogical(fromLast)).getIndex(); } - @Specialization(guards = {"!empty(x)"}) - protected int anyDuplicated(RAbstractContainer x, RAbstractContainer incomparables, byte fromLast) { + @Specialization(guards = {"notAbstractVector(incomparables)", "!empty(x)"}) + protected int anyDuplicatedTrueIncomparables(RAbstractVector x, Object incomparables, @SuppressWarnings("unused") byte fromLast) { initChildren(); RType xType = typeof.execute(x); - return DuplicationHelper.analyze(x, (RAbstractContainer) (castTypeNode.execute(incomparables, xType)), true, RRuntime.fromLogical(fromLast)).getIndex(); + // 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()); } @SuppressWarnings("unused") @Specialization(guards = "empty(x)") - protected int anyDuplicatedEmpty(RAbstractContainer x, RAbstractContainer incomparables, byte fromLast) { + protected int anyDuplicatedEmpty(RAbstractVector x, Object incomparables, byte fromLast) { return 0; } - @SuppressWarnings("unused") - @Specialization - protected int anyDuplicatedNull(RNull x, RAbstractContainer 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 b02a20b452417ce0cc22054770b83dee658b682a..09557dc390d69f495316c6f359cf837476aad32c 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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.RBehavior.READS_STATE; @@ -30,19 +31,17 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import java.util.ArrayList; 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.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; 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.RDataFactory; import com.oracle.truffle.r.runtime.data.RExternalPtr; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.DLL.DLLException; @@ -56,18 +55,19 @@ public class DynLoadFunctions { @RBuiltin(name = "dyn.load", visibility = OFF, kind = INTERNAL, parameterNames = {"lib", "local", "now", "unused"}, behavior = COMPLEX) public abstract static class DynLoad extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("lib").mustBe(stringValue()).asStringVector().mustBe(size(1), RError.Message.CHAR_ARGUMENT).findFirst(); + casts.arg("local").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("now").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("unused").mustBe(stringValue()).asStringVector().findFirst(); + } + @Specialization @TruffleBoundary - protected RList doDynLoad(RAbstractStringVector libVec, RAbstractLogicalVector localVec, byte now, @SuppressWarnings("unused") String unused) { - // Length checked by GnuR - if (libVec.getLength() > 1) { - throw RError.error(this, RError.Message.TYPE_EXPECTED, RType.Character.getName()); - } - String lib = libVec.getDataAt(0); - // Length not checked by GnuR - byte local = localVec.getDataAt(0); + protected RList doDynLoad(String lib, boolean local, boolean now, @SuppressWarnings("unused") String unused) { try { - DLLInfo dllInfo = DLL.loadPackageDLL(lib, asBoolean(local), asBoolean(now)); + DLLInfo dllInfo = DLL.loadPackageDLL(lib, local, now); return dllInfo.toRList(); } catch (DLLException ex) { // This is not a recoverable error @@ -77,13 +77,15 @@ public class DynLoadFunctions { } } - private static boolean asBoolean(byte b) { - return b == RRuntime.LOGICAL_TRUE ? true : false; - } } @RBuiltin(name = "dyn.unload", visibility = OFF, kind = INTERNAL, parameterNames = {"lib"}, behavior = COMPLEX) public abstract static class DynUnload extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("lib").mustBe(stringValue()).asStringVector().mustBe(size(1), RError.Message.CHAR_ARGUMENT).findFirst(); + } + @Specialization @TruffleBoundary protected RNull doDynunload(RAbstractStringVector lib) { @@ -116,12 +118,18 @@ public class DynLoadFunctions { } } - @RBuiltin(name = "is.loaded", kind = INTERNAL, parameterNames = {"symbol", "package", "type"}, behavior = READS_STATE) + @RBuiltin(name = "is.loaded", kind = INTERNAL, parameterNames = {"symbol", "PACKAGE", "type"}, behavior = READS_STATE) public abstract static class IsLoaded extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("symbol").mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst(); + casts.arg("PACKAGE").mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst(); + casts.arg("type").mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst(); + } + @Specialization @TruffleBoundary - protected byte isLoaded(RAbstractStringVector symbol, RAbstractStringVector packageName, RAbstractStringVector typeVec) { - String type = typeVec.getDataAt(0); + protected byte isLoaded(String symbol, String packageName, String type) { NativeSymbolType nst = null; switch (type) { case "": @@ -139,18 +147,22 @@ public class DynLoadFunctions { // Not an error in GnuR } DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(nst, null, null); - boolean found = DLL.findSymbol(symbol.getDataAt(0), packageName.getDataAt(0), rns) != DLL.SYMBOL_NOT_FOUND; + boolean found = DLL.findSymbol(symbol, packageName, rns) != DLL.SYMBOL_NOT_FOUND; return RRuntime.asLogical(found); } } - @RBuiltin(name = "getSymbolInfo", kind = INTERNAL, parameterNames = {"symbol", "package", "withReg"}, behavior = READS_STATE) + @RBuiltin(name = "getSymbolInfo", kind = INTERNAL, parameterNames = {"symbol", "package", "withRegistrationInfo"}, behavior = READS_STATE) public abstract static class GetSymbolInfo extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("symbol").mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst(); + casts.arg("withRegistrationInfo").mustBe(logicalValue()).asLogicalVector().findFirst().map(toBoolean()); + } @Specialization @TruffleBoundary - protected Object getSymbolInfo(RAbstractStringVector symbolVec, String packageName, byte withReg) { - String symbol = symbolVec.getDataAt(0); + protected Object getSymbolInfo(String symbol, String packageName, boolean withReg) { DLL.RegisteredNativeSymbol rns = DLL.RegisteredNativeSymbol.any(); long f = DLL.findSymbol(RRuntime.asString(symbol), packageName, rns); SymbolInfo symbolInfo = null; @@ -162,7 +174,7 @@ public class DynLoadFunctions { @Specialization(guards = "isDLLInfo(externalPtr)") @TruffleBoundary - protected Object getSymbolInfo(RAbstractStringVector symbolVec, RExternalPtr externalPtr, byte withReg) { + protected Object getSymbolInfo(RAbstractStringVector symbolVec, RExternalPtr externalPtr, boolean withReg) { DLL.DLLInfo dllInfo = DLL.getDLLInfoForId((int) externalPtr.getAddr()); if (dllInfo == null) { throw RError.error(this, RError.Message.REQUIRES_NAME_DLLINFO); @@ -178,20 +190,14 @@ public class DynLoadFunctions { return getResult(symbolInfo, withReg); } - private static Object getResult(DLL.SymbolInfo symbolInfo, byte withReg) { + private static Object getResult(DLL.SymbolInfo symbolInfo, boolean withReg) { if (symbolInfo != null) { - return symbolInfo.createRSymbolObject(new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.Any, null, null), RRuntime.fromLogical(withReg)); + return symbolInfo.createRSymbolObject(new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.Any, null, null), withReg); } else { return RNull.instance; } } - @SuppressWarnings("unused") - @Fallback - protected Object getSymbolInfo(Object symbol, Object packageName, Object withReg) { - throw RError.error(this, RError.Message.REQUIRES_NAME_DLLINFO); - } - protected static boolean isDLLInfo(RExternalPtr externalPtr) { return DLL.isDLLInfo(externalPtr); } 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 8957ee7919af8751dc8f0171a5a59c40b210f280..d8c5f44aa8a65b67506736c8bcf80556bba2d8f8 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 @@ -22,11 +22,12 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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.Fallback; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -38,31 +39,34 @@ public class EncodingFunctions { @RBuiltin(name = "Encoding", kind = INTERNAL, parameterNames = "x", behavior = PURE) public abstract static class Encoding extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.CHAR_VEC_ARGUMENT); + } + @Specialization protected RStringVector encoding(@SuppressWarnings("unused") RAbstractStringVector x) { // TODO implement properly return RDataFactory.createStringVectorFromScalar("unknown"); } - @SuppressWarnings("unused") - @Fallback - protected RStringVector encoding(Object x) { - throw RError.error(this, RError.Message.CHAR_VEC_ARGUMENT); - } } @RBuiltin(name = "setEncoding", kind = INTERNAL, parameterNames = {"x", "value"}, behavior = PURE) public abstract static class SetEncoding extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").defaultError(RError.SHOW_CALLER, 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"); + } + @Specialization - protected Object setEncoding(RAbstractStringVector x) { + protected Object setEncoding(RAbstractStringVector x, @SuppressWarnings("unused") RAbstractStringVector value) { // TODO implement properly return x; } - @SuppressWarnings("unused") - @Fallback - protected RStringVector setEncoding(Object x) { - throw RError.error(this, RError.Message.CHAR_VEC_ARGUMENT); - } } } 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 3218540666337c629535b77554f78f81e03d9f81..5f90889a70d473ecd14239d083a9bcb7676cf3aa 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 @@ -22,6 +22,10 @@ */ 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.instanceOf; +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.RDispatch.INTERNAL_GENERIC; import static com.oracle.truffle.r.runtime.RVisibility.OFF; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; @@ -35,12 +39,13 @@ 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.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.Frame; import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; 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; @@ -53,6 +58,7 @@ import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseDeoptimizeFrameNode; import com.oracle.truffle.r.runtime.RArguments; 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.Utils; @@ -70,16 +76,13 @@ import com.oracle.truffle.r.runtime.data.RPromise; 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.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.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.FrameSlotChangeMonitor; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; -import com.oracle.truffle.r.runtime.nodes.RNode; /** * Encapsulates all the builtins related to R environments as nested static classes. @@ -93,6 +96,11 @@ public class EnvFunctions { @RBuiltin(name = "as.environment", kind = PRIMITIVE, parameterNames = {"fun"}, dispatch = INTERNAL_GENERIC, behavior = COMPLEX) public abstract static class AsEnvironment extends Adapter { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("fun").mapIf(numericValue(), asIntegerVector()); + } + @Specialization protected REnvironment asEnvironment(@SuppressWarnings("unused") RNull rnull) { throw RError.error(this, RError.Message.AS_ENV_NULL_DEFUNCT); @@ -104,39 +112,46 @@ public class EnvFunctions { } @Specialization - protected REnvironment asEnvironment(VirtualFrame frame, RAbstractDoubleVector posVec) { - return asEnvironmentInt(frame, (int) posVec.getDataAt(0)); - } - - @Specialization - protected REnvironment asEnvironmentInt(VirtualFrame frame, RAbstractIntVector posVec) { - return asEnvironmentInt(frame, posVec.getDataAt(0)); - } - - private REnvironment asEnvironmentInt(VirtualFrame frame, int pos) { - if (pos == -1) { - Frame callerFrame = Utils.getCallerFrame(frame, FrameAccess.MATERIALIZE); - if (callerFrame == null) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NO_ENCLOSING_ENVIRONMENT); + protected Object asEnvironmentInt(VirtualFrame frame, RAbstractIntVector pos) { + if (pos.getLength() == 0) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(this, Message.INVALID_ARGUMENT, "pos"); + } + Object[] results = pos.getLength() == 1 ? null : new Object[pos.getLength()]; + for (int i = 0; i < pos.getLength(); i++) { + REnvironment env; + int p = pos.getDataAt(i); + if (p == -1) { + Frame callerFrame = Utils.getCallerFrame(frame, FrameAccess.MATERIALIZE); + if (callerFrame == null) { + errorProfile.enter(); + throw RError.error(this, RError.Message.NO_ENCLOSING_ENVIRONMENT); + } else { + env = REnvironment.frameToEnvironment(callerFrame.materialize()); + } } else { - return REnvironment.frameToEnvironment(callerFrame.materialize()); + String[] searchPath = REnvironment.searchPath(); + if (p == searchPath.length + 1) { + // although the empty env does not appear in the result of "search", and it + // is + // not accessible by name, GnuR allows it to be accessible by index + env = REnvironment.emptyEnv(); + } else if ((p <= 0) || (p > searchPath.length + 1)) { + errorProfile.enter(); + throw RError.error(this, RError.Message.INVALID_ARGUMENT, "pos"); + } else { + env = REnvironment.lookupOnSearchPath(searchPath[p - 1]); + } + } + if (pos.getLength() == 1) { + return env; } } - String[] searchPath = REnvironment.searchPath(); - if (pos == searchPath.length + 1) { - // although the empty env does not appear in the result of "search", and it is - // not accessible by name, GnuR allows it to be accessible by index - return REnvironment.emptyEnv(); - } else if ((pos <= 0) || (pos > searchPath.length + 1)) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "pos"); - } else { - return REnvironment.lookupOnSearchPath(searchPath[pos - 1]); - } + return RDataFactory.createList(results); } @Specialization + @TruffleBoundary protected REnvironment asEnvironment(RAbstractStringVector nameVec) { String name = nameVec.getDataAt(0); String[] searchPath = REnvironment.searchPath(); @@ -225,9 +240,10 @@ public class EnvFunctions { REnvironment target; if (!(envir instanceof REnvironment)) { if (parentFrameNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); parentFrameNode = insert(FrameFunctionsFactory.ParentFrameNodeGen.create(null)); } - env = (REnvironment) parentFrameNode.execute(frame, 2); + env = parentFrameNode.execute(frame, 2); } else { env = (REnvironment) envir; } @@ -256,11 +272,16 @@ public class EnvFunctions { @RBuiltin(name = "parent.env", kind = INTERNAL, parameterNames = {"env"}, behavior = READS_FRAME) public abstract static class ParentEnv extends Adapter { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("env").mustBe(instanceOf(REnvironment.class), RError.SHOW_CALLER, Message.ARGUMENT_NOT_ENVIRONMENT); + } + @Specialization protected REnvironment parentenv(REnvironment env) { if (env == REnvironment.emptyEnv()) { errorProfile.enter(); - throw RError.error(this, RError.Message.EMPTY_NO_PARENT); + throw RError.error(RError.SHOW_CALLER, RError.Message.EMPTY_NO_PARENT); } return env.getParent(); } @@ -269,11 +290,17 @@ public class EnvFunctions { @RBuiltin(name = "parent.env<-", kind = INTERNAL, parameterNames = {"env", "value"}, behavior = COMPLEX) public abstract static class SetParentEnv extends Adapter { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("env").mustBe(instanceOf(REnvironment.class), Message.NON_LANG_ASSIGNMENT_TARGET); + casts.arg("value").mustNotBeNull(Message.USE_NULL_ENV_DEFUNCT, "NULL").mustBe(instanceOf(REnvironment.class), Message.ARGUMENT_NAME_NOT_ENVIRONMENT, "parent"); + } + @Specialization @TruffleBoundary protected REnvironment setParentenv(REnvironment env, REnvironment parent) { if (env == REnvironment.emptyEnv()) { - throw RError.error(this, RError.Message.CANNOT_SET_PARENT); + throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_SET_PARENT); } env.setParent(parent); return env; @@ -292,9 +319,12 @@ public class EnvFunctions { @RBuiltin(name = "environment", kind = INTERNAL, parameterNames = {"fun"}, behavior = COMPLEX) public abstract static class Environment extends RBuiltinNode { + private static RAttributeProfiles attributeProfile = RAttributeProfiles.create(); + private final ConditionProfile attributable = ConditionProfile.createBinaryProfile(); + @Specialization - protected Object environment(VirtualFrame frame, @SuppressWarnings("unused") RNull fun, // - @Cached("new()") GetCallerFrameNode callerFrame, // + protected Object environment(VirtualFrame frame, @SuppressWarnings("unused") RNull fun, + @Cached("new()") GetCallerFrameNode callerFrame, @Cached("new()") PromiseDeoptimizeFrameNode deoptFrameNode) { MaterializedFrame matFrame = callerFrame.execute(frame); @@ -307,8 +337,8 @@ public class EnvFunctions { * Returns the environment that {@code func} was created in. */ @Specialization - protected Object environment(RFunction fun, // - @Cached("createBinaryProfile()") ConditionProfile noEnvProfile, // + protected Object environment(RFunction fun, + @Cached("createBinaryProfile()") ConditionProfile noEnvProfile, @Cached("createBinaryProfile()") ConditionProfile createProfile) { Frame enclosing = fun.getEnclosingFrame(); if (noEnvProfile.profile(enclosing == null)) { @@ -322,27 +352,40 @@ public class EnvFunctions { } @Specialization(guards = "isRFormula(formula)") - protected Object environment(RLanguage formula, // + protected Object environment(RLanguage formula, @Cached("create()") RAttributeProfiles attrProfiles) { Object result = formula.getAttr(attrProfiles, RRuntime.DOT_ENVIRONMENT); return result == null ? RNull.instance : result; } @Specialization(guards = {"!isRNull(fun)", "!isRFunction(fun)", "!isRFormula(fun)"}) - protected Object environment(@SuppressWarnings("unused") Object fun) { - // Not an error according to GnuR - return RNull.instance; + protected Object environment(Object fun) { + if (attributable.profile(fun instanceof RAttributable)) { + Object attr = ((RAttributable) fun).getAttr(attributeProfile, RRuntime.DOT_ENVIRONMENT); + return attr == null ? RNull.instance : attr; + } else { + // Not an error according to GnuR + return RNull.instance; + } } } @RBuiltin(name = "environment<-", kind = PRIMITIVE, parameterNames = {"env", "value"}, behavior = COMPLEX) public abstract static class UpdateEnvironment extends RBuiltinNode { - private static RAttributeProfiles attributeProfile = RAttributeProfiles.create(); + private final RAttributeProfiles attributeProfile = RAttributeProfiles.create(); + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("value").allowNull().mustBe(REnvironment.class, Message.REPLACEMENT_NOT_ENVIRONMENT); + } @Specialization @TruffleBoundary - protected Object updateEnvironment(RFunction fun, REnvironment env) { + protected static Object updateEnvironment(RFunction fun, REnvironment env) { + if (env.getFrame() == fun.getEnclosingFrame()) { + return fun; + } MaterializedFrame enclosingFrame = env.getFrame(); assert !(enclosingFrame instanceof VirtualEvalFrame); @@ -352,43 +395,49 @@ public class EnvFunctions { return RDataFactory.createFunction(fun.getName(), target, null, enclosingFrame); } - @SuppressWarnings("unused") @Specialization @TruffleBoundary - protected Object updateEnvironment(RFunction fun, RNull env) { + protected Object updateEnvironment(@SuppressWarnings("unused") RFunction fun, @SuppressWarnings("unused") RNull env) { throw RError.error(this, RError.Message.USE_NULL_ENV_DEFUNCT); } - protected Object updateEnvironmentNonFunction(Object obj, Object env) { - if (env == RNull.instance || env instanceof REnvironment) { - if (obj instanceof RAttributable) { - RAttributable attributable = (RAttributable) obj; - if (env == RNull.instance) { - attributable.removeAttr(attributeProfile, RRuntime.DOT_ENVIRONMENT); - } else { - attributable.setAttr(RRuntime.DOT_ENVIRONMENT, env); - } - return obj; - } else { - throw RInternalError.shouldNotReachHere("environment<- called on non-attributable object"); - } - } else { - throw RError.error(this, RError.Message.REPLACEMENT_NOT_ENVIRONMENT); - } + @Specialization + @TruffleBoundary + protected static Object updateEnvironment(RAbstractContainer obj, REnvironment env) { + return updateEnvironment((RAttributable) obj, env); } @Specialization @TruffleBoundary - protected Object updateEnvironment(RAbstractContainer obj, Object env) { - return updateEnvironmentNonFunction(obj, env); + protected static Object updateEnvironment(RAttributable obj, REnvironment env) { + obj.setAttr(RRuntime.DOT_ENVIRONMENT, env); + return obj; } - @Fallback + @Specialization + @TruffleBoundary + protected Object updateEnvironment(RAbstractContainer obj, RNull env) { + return updateEnvironment((RAttributable) obj, env); + } + + @Specialization @TruffleBoundary - protected Object updateEnvironment(Object obj, Object env) { - return updateEnvironmentNonFunction(obj, env); + protected Object updateEnvironment(RAttributable obj, @SuppressWarnings("unused") RNull env) { + obj.removeAttr(attributeProfile, RRuntime.DOT_ENVIRONMENT); + return obj; } + @Specialization + @TruffleBoundary + protected static Object updateEnvironment(RNull obj, @SuppressWarnings("unused") RNull env) { + return obj; + } + + @Specialization + @TruffleBoundary + protected Object updateEnvironment(@SuppressWarnings("unused") RNull obj, @SuppressWarnings("unused") REnvironment env) { + throw RError.error(this, Message.SET_ATTRIBUTES_ON_NULL); + } } @RBuiltin(name = "environmentName", kind = INTERNAL, parameterNames = {"fun"}, behavior = PURE) @@ -411,13 +460,15 @@ public class EnvFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(2); + casts.arg("hash").mustNotBeNull().asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + casts.arg("parent").mustNotBeNull().mustBe(REnvironment.class, Message.MUST_BE_ENVIRON); + casts.arg("size").mustNotBeNull().asIntegerVector().findFirst(0); } @Specialization @TruffleBoundary - protected REnvironment newEnv(byte hash, REnvironment parent, int size) { - REnvironment env = RDataFactory.createNewEnv(null, RRuntime.fromLogical(hash), size); + protected REnvironment newEnv(boolean hash, REnvironment parent, int size) { + REnvironment env = RDataFactory.createNewEnv(null, hash, size); RArguments.initializeEnclosingFrame(env.getFrame(), parent.getFrame()); return env; } @@ -434,73 +485,91 @@ public class EnvFunctions { @RBuiltin(name = "lockEnvironment", visibility = OFF, kind = INTERNAL, parameterNames = {"env", "bindings"}, behavior = COMPLEX) public abstract static class LockEnvironment extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("env").mustNotBeNull().mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT); + // TODO: the actual interpretation of this parameter remains dubious + casts.arg("bindings").mustNotBeNull().asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + } + @Specialization - protected Object lockEnvironment(REnvironment env, byte bindings) { - env.lock(bindings == RRuntime.LOGICAL_TRUE); + protected Object lockEnvironment(REnvironment env, boolean bindings) { + env.lock(bindings); return RNull.instance; } } @RBuiltin(name = "environmentIsLocked", kind = INTERNAL, parameterNames = {"env"}, behavior = PURE) public abstract static class EnvironmentIsLocked extends RBuiltinNode { + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("env").mustNotBeNull().mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT); + } + @Specialization protected Object lockEnvironment(REnvironment env) { return RDataFactory.createLogicalVectorFromScalar(env.isLocked()); } } - private static RuntimeException typeError(RBaseNode invokingNode, Object sym, Object env) { - if (!(sym instanceof RSymbol)) { - throw RError.error(invokingNode, RError.Message.NOT_A_SYMBOL); - } else { - assert !(env instanceof REnvironment); - throw RError.error(invokingNode, RError.Message.NOT_AN_ENVIRONMENT); - } - } - @RBuiltin(name = "lockBinding", visibility = OFF, kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = COMPLEX) public abstract static class LockBinding extends RBuiltinNode { + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("sym").mustNotBeNull().mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL); + casts.arg("env").mustNotBeNull().mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT); + } + @Specialization protected Object lockBinding(RSymbol sym, REnvironment env) { env.lockBinding(sym.getName()); return RNull.instance; } - - @Fallback - protected Object lockBinding(Object sym, Object env) { - throw typeError(this, sym, env); - } } @RBuiltin(name = "unlockBinding", visibility = OFF, kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = COMPLEX) public abstract static class UnlockBinding extends RBuiltinNode { + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("sym").mustNotBeNull().mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL); + casts.arg("env").mustNotBeNull().mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT); + } + @Specialization protected RNull unlockBinding(RSymbol sym, REnvironment env) { env.unlockBinding(sym.getName()); return RNull.instance; } - - @Fallback - protected Object unlockBindings(Object sym, Object env) { - throw typeError(this, sym, env); - } } @RBuiltin(name = "bindingIsLocked", kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = PURE) public abstract static class BindingIsLocked extends RBuiltinNode { + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("sym").mustNotBeNull().mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL); + casts.arg("env").mustNotBeNull().mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT); + } + @Specialization protected Object bindingIsLocked(RSymbol sym, REnvironment env) { return RDataFactory.createLogicalVectorFromScalar(env.bindingIsLocked(sym.getName())); } - - @Fallback - protected Object bindingIsLocked(Object sym, Object env) { - throw typeError(this, sym, env); - } } @RBuiltin(name = "makeActiveBinding", visibility = OFF, kind = INTERNAL, parameterNames = {"sym", "fun", "env"}, behavior = COMPLEX) public abstract static class MakeActiveBinding extends RBuiltinNode { + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("sym").mustNotBeNull().mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL); + casts.arg("fun").mustNotBeNull().mustBe(RFunction.class, RError.SHOW_CALLER, Message.NOT_A_FUNCTION); + casts.arg("env").mustNotBeNull().mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT); + } + @SuppressWarnings("unused") @Specialization protected Object makeActiveBinding(Object sym, Object fun, Object env) { @@ -511,9 +580,16 @@ public class EnvFunctions { @RBuiltin(name = "bindingIsActive", kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = PURE) public abstract static class BindingIsActive extends RBuiltinNode { + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("sym").mustNotBeNull().mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL); + casts.arg("env").mustNotBeNull().mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT); + } + @SuppressWarnings("unused") @Specialization - protected Object bindingIsActive(Object sym, Object fun, Object env) { + protected Object bindingIsActive(Object sym, Object env) { // TODO implement throw RError.nyi(this, "bindingIsActive"); } @@ -524,20 +600,25 @@ public class EnvFunctions { @Child private CopyNode copy; + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustNotBeNull().mustBe(REnvironment.class, RError.SHOW_CALLER, 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()); + } + private Object copy(VirtualFrame frame, Object operand) { if (copy == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - copy = insert(CopyNodeGen.create(null)); + copy = insert(CopyNodeGen.create()); } return copy.execute(frame, operand); } @Specialization - protected RList envToListAllNames(VirtualFrame frame, REnvironment env, RAbstractLogicalVector allNamesVec, RAbstractLogicalVector sortedVec) { + protected RList envToListAllNames(VirtualFrame frame, REnvironment env, boolean allNames, boolean sorted) { // according to the docs it is expected to be slow as it creates a copy of environment // objects - boolean allNames = allNamesVec.getLength() == 0 || allNamesVec.getDataAt(0) == RRuntime.LOGICAL_FALSE ? false : true; - boolean sorted = sortedVec.getLength() == 0 || sortedVec.getDataAt(0) == RRuntime.LOGICAL_FALSE ? false : true; RStringVector keys = envls(env, allNames, sorted); Object[] data = new Object[keys.getLength()]; for (int i = 0; i < data.length; i++) { @@ -555,8 +636,8 @@ public class EnvFunctions { } } - @NodeChild("operand") - protected abstract static class CopyNode extends RNode { + @TypeSystemReference(RTypes.class) + protected abstract static class CopyNode extends Node { protected abstract Object execute(VirtualFrame frame, Object o); @@ -566,7 +647,7 @@ public class EnvFunctions { private Object recursiveCopy(VirtualFrame frame, Object operand) { if (recursiveCopy == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - recursiveCopy = insert(CopyNodeGen.create(null)); + recursiveCopy = insert(CopyNodeGen.create()); } return recursiveCopy.execute(frame, operand); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java similarity index 62% rename from com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java rename to com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java index 2175b5841baeaa0313282dd7634809a4bafb0ff8..150c07c5653314a9ed369999c6b72ba5b96805d4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java @@ -22,20 +22,23 @@ */ 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.runtime.RVisibility.CUSTOM; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; -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.RASTUtils; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.builtin.base.EvalFunctionsFactory.EvalEnvCastNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.EvalNodeGen.EvalEnvCastNodeGen; +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.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.RCaller; -import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; @@ -44,13 +47,15 @@ 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.RSymbol; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** * Contains the {@code eval} {@code .Internal} implementation. */ -public class EvalFunctions { +@RBuiltin(name = "eval", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"expr", "envir", "enclos"}, behavior = COMPLEX) +public abstract class Eval extends RBuiltinNode { /** * Eval takes two arguments that specify the environment where the expression should be @@ -59,7 +64,7 @@ public class EvalFunctions { * values that may make it into the internal code. This node handles these. See the * documentation of eval for more details. */ - public abstract static class EvalEnvCast extends RBaseNode { + abstract static class EvalEnvCast extends RBaseNode { public abstract REnvironment execute(Object env, Object enclos); @@ -108,40 +113,61 @@ public class EvalFunctions { // This can happen when envir is a pairlist and enclos is explicitly set to NULL return REnvironment.createFromList(attributeProfiles, list.toRList(), REnvironment.baseEnv()); } + } - @Fallback - @TruffleBoundary - protected REnvironment doEval(@SuppressWarnings("unused") Object env, @SuppressWarnings("unused") Object enclos) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); - } + @Child private EvalEnvCast envCast = EvalEnvCastNodeGen.create(); + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("envir").allowNull().mustBe(instanceOf(REnvironment.class).or(instanceOf(RList.class)).or(instanceOf(RPairList.class))); + casts.arg("enclos").allowNull().mustBe(REnvironment.class); } - @RBuiltin(name = "eval", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"expr", "envir", "enclos"}, behavior = COMPLEX) - public abstract static class Eval extends RBuiltinNode { - - @TruffleBoundary - protected Object doEvalBody(RCaller rCaller, Object exprArg, REnvironment envir) { - Object expr = RASTUtils.checkForRSymbol(exprArg); - - if (expr instanceof RExpression) { - return RContext.getEngine().eval((RExpression) expr, envir, rCaller); - } else if (expr instanceof RLanguage) { - return RContext.getEngine().eval((RLanguage) expr, envir, rCaller); - } else { - // just return value - return expr; - } + @Specialization + protected Object doEval(VirtualFrame frame, RLanguage expr, Object envir, Object enclos) { + RCaller rCaller = RCaller.create(frame, getOriginalCall()); + REnvironment environment = envCast.execute(envir, enclos); + try { + return RContext.getEngine().eval(expr, environment, rCaller); + } finally { + visibility.executeAfterCall(frame, rCaller); } + } - @Specialization - protected Object doEval(VirtualFrame frame, Object expr, Object envir, Object enclos, // - @Cached("createCast()") EvalEnvCast envCast) { - // Note: fallback for invalid combinations of envir and enclos is in EvalEnvCastNode - return doEvalBody(RCaller.create(frame, getOriginalCall()), expr, envCast.execute(envir, enclos)); + @Specialization + protected Object doEval(VirtualFrame frame, RExpression expr, Object envir, Object enclos) { + RCaller rCaller = RCaller.create(frame, getOriginalCall()); + REnvironment environment = envCast.execute(envir, enclos); + try { + return RContext.getEngine().eval(expr, environment, rCaller); + } finally { + visibility.executeAfterCall(frame, rCaller); } + } - protected EvalEnvCast createCast() { - return EvalEnvCastNodeGen.create(); + protected static Get createGet() { + return GetNodeGen.create(null); + } + + @Specialization + protected Object doEval(VirtualFrame frame, RSymbol expr, Object envir, Object enclos, + @Cached("createGet()") Get get) { + REnvironment environment = envCast.execute(envir, enclos); + + try { + // no need to do the full eval for symbols: just do the lookup + return get.execute(frame, expr.getName(), environment, RType.Any.getName(), true); + } finally { + visibility.execute(frame, true); } } + + @Fallback + protected Object doEval(VirtualFrame frame, Object expr, Object envir, Object enclos) { + // just return value + envCast.execute(envir, enclos); + visibility.execute(frame, true); + return expr; + } } 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 de672880e0c78411ec1a3d70de0cc9e6e7bc69f7..e70b055c123b0f7e907fa223ab80bec3434eba1b 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 @@ -22,6 +22,9 @@ */ 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.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -29,13 +32,14 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.attributes.TypeFromModeNode; import com.oracle.truffle.r.nodes.attributes.TypeFromModeNodeGen; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; +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.RPromise; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; @RBuiltin(name = "exists", kind = INTERNAL, parameterNames = {"x", "envir", "mode", "inherits"}, behavior = PURE) @@ -43,14 +47,24 @@ public abstract class Exists extends RBuiltinNode { @Child private TypeFromModeNode typeFromMode = TypeFromModeNodeGen.create(); - public abstract byte execute(RAbstractStringVector nameVec, REnvironment env, String mode, byte inherits); + /** + * Explicit execute declaration, because it is invoked by the fast-path version. + */ + public abstract byte execute(String nameVec, REnvironment env, String mode, boolean inherits); + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(stringValue(), Message.INVALID_FIRST_ARGUMENT).asStringVector().findFirst(); + casts.arg("envir").mustBe(REnvironment.class); + casts.arg("mode").mustBe(stringValue()).asStringVector().findFirst(); + casts.arg("inherits").mustBe(numericValue()).asLogicalVector().findFirst().map(toBoolean()); + } @Specialization @TruffleBoundary - protected byte existsStringEnv(RAbstractStringVector nameVec, REnvironment env, String mode, byte inherits) { - String name = nameVec.getDataAt(0); + protected byte existsStringEnv(String name, REnvironment env, String mode, boolean inherits) { RType modeType = typeFromMode.execute(mode); - if (inherits == RRuntime.LOGICAL_FALSE) { + if (!inherits) { Object obj = env.get(name); if (modeType != RType.Any && obj instanceof RPromise) { obj = PromiseHelperNode.evaluateSlowPath(null, (RPromise) obj); 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 a9a681eb660cc2c2786b9d3dae63802b95cc869a..a0c481ef01afc35a7d93f9f1309407fd2debe721 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 @@ -34,7 +34,6 @@ import com.oracle.truffle.r.runtime.ArgumentsSignature; 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.RList; import com.oracle.truffle.r.runtime.data.RPromise; @RBuiltin(name = "expression", kind = PRIMITIVE, parameterNames = {"..."}, nonEvalArgs = 0, behavior = PURE) @@ -55,30 +54,27 @@ public abstract class Expression extends RBuiltinNode { for (int i = 0; i < argValues.length; i++) { data[i] = convert((RPromise) argValues[i]); } - RList list; if (hasNonNull) { String[] names = new String[signature.getLength()]; for (int i = 0; i < names.length; i++) { names[i] = signature.getName(i); } - list = RDataFactory.createList(data, RDataFactory.createStringVector(names, RDataFactory.COMPLETE_VECTOR)); + return RDataFactory.createExpression(data, RDataFactory.createStringVector(names, RDataFactory.COMPLETE_VECTOR)); } else { - list = RDataFactory.createList(data); + return RDataFactory.createExpression(data); } - return RDataFactory.createExpression(list); } @Specialization protected Object doExpression(RPromise language) { - RList list = RDataFactory.createList(new Object[]{convert(language)}); - return RDataFactory.createExpression(list); + return RDataFactory.createExpression(new Object[]{convert(language)}); } private Object convert(RPromise promise) { if (isEvaluatedProfile.profile(promise.isEvaluated())) { return promise.getValue(); } else { - return RASTUtils.createLanguageElement(RASTUtils.unwrap(promise.getRep())); + return RASTUtils.createLanguageElement(promise.getRep().asRSyntaxNode()); } } } 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 9d902b5d481e52d677b754eee866fc0df6b3bf84..6e46110cda9b9842d1ae032e91ccc6d405da6152 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 @@ -11,6 +11,15 @@ */ 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.gte; +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.logicalNA; +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.runtime.RVisibility.OFF; import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -45,7 +54,6 @@ import java.util.stream.Stream; 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.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; @@ -62,6 +70,8 @@ import com.oracle.truffle.r.runtime.data.RList; 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.RSymbol; +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.RAbstractStringVector; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; @@ -78,15 +88,13 @@ public class FileFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1); + casts.arg("names").mustBe(stringValue()).asStringVector(); + casts.arg("mode").asIntegerVector().findFirst().mustBe(gte(0).and(lte(7))); } @Specialization @TruffleBoundary protected Object fileAccess(RAbstractStringVector names, int mode) { - if (mode == RRuntime.INT_NA || mode < 0 || mode > 7) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "mode"); - } int[] data = new int[names.getLength()]; for (int i = 0; i < data.length; i++) { File file = new File(Utils.tildeExpand(names.getDataAt(i))); @@ -110,6 +118,12 @@ public class FileFunctions { @RBuiltin(name = "file.append", kind = INTERNAL, parameterNames = {"file1", "file2"}, behavior = IO) public abstract static class FileAppend extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("file1").mustBe(stringValue()).asStringVector(); + casts.arg("file2").mustBe(stringValue()).asStringVector(); + } + @Specialization @TruffleBoundary protected RLogicalVector doFileAppend(RAbstractStringVector file1Vec, RAbstractStringVector file2Vec) { @@ -200,6 +214,11 @@ public class FileFunctions { @RBuiltin(name = "file.create", kind = INTERNAL, parameterNames = {"vec", "showWarnings"}, behavior = IO) public abstract static class FileCreate extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("vec").mustBe(stringValue()).asStringVector(); + casts.arg("showWarnings").asLogicalVector().findFirst().mapIf(logicalNA(), constant(RRuntime.LOGICAL_FALSE)); + } @Specialization @TruffleBoundary @@ -225,11 +244,6 @@ public class FileFunctions { return RDataFactory.createLogicalVector(status, RDataFactory.COMPLETE_VECTOR); } - @Fallback - @TruffleBoundary - protected Object doFileCreate(@SuppressWarnings("unused") Object x, @SuppressWarnings("unused") Object y) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "file"); - } } @RBuiltin(name = "file.info", kind = INTERNAL, parameterNames = {"fn", "extra_cols"}, behavior = IO) @@ -247,7 +261,7 @@ public class FileFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.firstBoolean(1, "extra_cols"); + casts.arg("extra_cols").asLogicalVector().findFirst().map(toBoolean()); } @Specialization @@ -394,7 +408,13 @@ public class FileFunctions { } } - abstract static class FileLinkAdaptor extends RBuiltinNode { + private abstract static class FileLinkAdaptor extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("from").mustBe(stringValue(), RError.Message.INVALID_FIRST_FILENAME).asStringVector(); + casts.arg("to").mustBe(stringValue(), RError.Message.INVALID_SECOND_FILENAME).asStringVector(); + } + protected Object doFileLink(RAbstractStringVector vecFrom, RAbstractStringVector vecTo, boolean symbolic) { int lenFrom = vecFrom.getLength(); int lenTo = vecTo.getLength(); @@ -440,11 +460,6 @@ public class FileFunctions { return doFileLink(vecFrom, vecTo, false); } - @Fallback - @TruffleBoundary - protected Object doFileLink(@SuppressWarnings("unused") Object from, @SuppressWarnings("unused") Object to) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "file"); - } } @RBuiltin(name = "file.symlink", kind = INTERNAL, parameterNames = {"from", "to"}, behavior = IO) @@ -455,16 +470,16 @@ public class FileFunctions { return doFileLink(vecFrom, vecTo, true); } - @Fallback - @TruffleBoundary - protected Object doFileSymLink(@SuppressWarnings("unused") Object from, @SuppressWarnings("unused") Object to) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "file"); - } } - @RBuiltin(name = "file.remove", kind = INTERNAL, parameterNames = {"vec"}, behavior = IO) + @RBuiltin(name = "file.remove", kind = INTERNAL, parameterNames = {"file"}, behavior = IO) public abstract static class FileRemove extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("file").mustBe(stringValue(), RError.Message.INVALID_FIRST_FILENAME).asStringVector(); + } + @Specialization @TruffleBoundary protected Object doFileRemove(RAbstractStringVector vec) { @@ -485,15 +500,16 @@ public class FileFunctions { return RDataFactory.createLogicalVector(status, RDataFactory.COMPLETE_VECTOR); } - @Fallback - @TruffleBoundary - protected Object doFileRemove(@SuppressWarnings("unused") Object x) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "file"); - } } @RBuiltin(name = "file.rename", kind = INTERNAL, parameterNames = {"from", "to"}, behavior = IO) public abstract static class FileRename extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("from").mustBe(stringValue()).asStringVector(); + casts.arg("to").mustBe(stringValue()).asStringVector(); + } + @Specialization @TruffleBoundary protected Object doFileRename(RAbstractStringVector vecFrom, RAbstractStringVector vecTo) { @@ -520,16 +536,16 @@ public class FileFunctions { return RDataFactory.createLogicalVector(status, RDataFactory.COMPLETE_VECTOR); } - @Fallback - @TruffleBoundary - protected Object doFileRename(@SuppressWarnings("unused") Object from, @SuppressWarnings("unused") Object to) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "file"); - } } - @RBuiltin(name = "file.exists", kind = INTERNAL, parameterNames = {"vec"}, behavior = IO) + @RBuiltin(name = "file.exists", kind = INTERNAL, parameterNames = {"file"}, behavior = IO) public abstract static class FileExists extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("file").mustBe(stringValue()).asStringVector(); + } + @Specialization @TruffleBoundary protected Object doFileExists(RAbstractStringVector vec) { @@ -547,10 +563,6 @@ public class FileFunctions { return RDataFactory.createLogicalVector(status, RDataFactory.COMPLETE_VECTOR); } - @Fallback - protected Object doFileExists(@SuppressWarnings("unused") Object vec) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "file"); - } } // TODO Implement all the options @@ -559,17 +571,31 @@ public class FileFunctions { private static final String DOT = "."; private static final String DOTDOT = ".."; + @Override + protected void createCasts(CastBuilder casts) { + 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()); + } + @SuppressWarnings("unused") @Specialization @TruffleBoundary - protected RStringVector doListFiles(RAbstractStringVector vec, RNull patternVec, byte allFiles, byte fullNames, byte recursive, byte ignoreCase, byte includeDirs, byte noDotDot) { + protected RStringVector doListFiles(RAbstractStringVector vec, RNull patternVec, boolean allFiles, boolean fullNames, boolean recursive, boolean ignoreCase, boolean includeDirs, + boolean noDotDot) { return doListFilesBody(vec, null, allFiles, fullNames, recursive, ignoreCase, includeDirs, noDotDot); } @Specialization @TruffleBoundary - protected RStringVector doListFiles(RAbstractStringVector vec, RAbstractStringVector patternVec, byte allFiles, byte fullNames, byte recursive, byte ignoreCase, byte includeDirs, - byte noDotDot) { + protected RStringVector doListFiles(RAbstractStringVector vec, RAbstractStringVector patternVec, boolean allFiles, boolean fullNames, boolean recursive, boolean ignoreCase, + boolean includeDirs, + boolean noDotDot) { /* * Pattern in first element of vector, remaining elements are ignored (as per GnuR). * N.B. The pattern matches file names not paths, which means we cannot just use the @@ -577,20 +603,22 @@ public class FileFunctions { */ String pattern = null; - if (!(patternVec.getLength() == 0 || patternVec.getDataAt(0).length() == 0)) { - pattern = patternVec.getDataAt(0); + if (patternVec.getLength() > 0) { + if (RRuntime.isNA(patternVec.getDataAt(0))) { + throw RError.error(this, RError.Message.INVALID_ARGUMENT, "pattern"); + } else { + pattern = patternVec.getDataAt(0); + } } + return doListFilesBody(vec, pattern, allFiles, fullNames, recursive, ignoreCase, includeDirs, noDotDot); } - private RStringVector doListFilesBody(RAbstractStringVector vec, String patternString, byte allFilesL, byte fullNamesL, byte recursiveL, byte ignoreCaseL, byte includeDirsL, byte noDotDotL) { - boolean allFiles = RRuntime.fromLogical(allFilesL); - boolean fullNames = RRuntime.fromLogical(fullNamesL); - boolean recursive = RRuntime.fromLogical(recursiveL); + private RStringVector doListFilesBody(RAbstractStringVector vec, String patternString, boolean allFiles, boolean fullNames, boolean recursive, + boolean ignoreCaseIn, boolean includeDirsIn, boolean noDotDot) { + boolean includeDirs = !recursive || includeDirsIn; @SuppressWarnings("unused") - boolean ignoreCase = check(ignoreCaseL, "ignoreCase"); - boolean includeDirs = !recursive || RRuntime.fromLogical(includeDirsL); - boolean noDotDot = RRuntime.fromLogical(noDotDotL); + boolean ignoreCase = check(ignoreCaseIn, "ignoreCase"); Pattern pattern = patternString == null ? null : Pattern.compile(patternString); // Curiously the result is not a vector of same length as the input, // as typical for R, but a single vector, which means duplicates may occur @@ -644,10 +672,10 @@ public class FileFunctions { Arrays.sort(data); return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR); } + } - private boolean check(byte valueLogical, String argName) { - boolean value = RRuntime.fromLogical(valueLogical); + private boolean check(boolean value, String argName) { if (value) { RError.warning(this, RError.Message.GENERIC, "'" + argName + "'" + " is not implemented"); } @@ -683,13 +711,18 @@ public class FileFunctions { } } - @RBuiltin(name = "list.dirs", kind = INTERNAL, parameterNames = {"path", "full.names", "recursive"}, behavior = IO) + @RBuiltin(name = "list.dirs", kind = INTERNAL, parameterNames = {"directory", "full.names", "recursive"}, behavior = IO) public abstract static class ListDirs extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("directory").mustBe(stringValue()).asStringVector(); + casts.arg("full.names").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("recursive").asLogicalVector().findFirst().notNA().map(toBoolean()); + } + @Specialization @TruffleBoundary - protected RStringVector listDirs(RAbstractStringVector paths, byte fullNamesL, byte recursiveL) { - boolean fullNames = RRuntime.fromLogical(fullNamesL); - boolean recursive = RRuntime.fromLogical(recursiveL); + protected RStringVector listDirs(RAbstractStringVector paths, boolean fullNames, boolean recursive) { ArrayList<String> dirList = new ArrayList<>(); for (int i = 0; i < paths.getLength(); i++) { String vecPathString = paths.getDataAt(i); @@ -736,12 +769,18 @@ public class FileFunctions { @RBuiltin(name = "file.path", kind = INTERNAL, parameterNames = {"paths", "fsep"}, behavior = IO) public abstract static class FilePath extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("paths").mustBe(instanceOf(RList.class), RError.Message.INVALID_FIRST_ARGUMENT); + casts.arg("fsep").mustBe(stringValue()).asStringVector().findFirst().notNA(); + } + @Child private CastStringNode castStringNode; private CastStringNode initCastStringNode() { if (castStringNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - castStringNode = insert(CastStringNodeGen.create(false, false, false, false)); + castStringNode = insert(CastStringNodeGen.create(false, false, false)); } return castStringNode; } @@ -749,12 +788,13 @@ public class FileFunctions { @SuppressWarnings("unused") @Specialization(guards = "lengthZero(vec)") @TruffleBoundary - protected RStringVector doFilePathZero(RList vec, RAbstractStringVector fsep) { + protected RStringVector doFilePathZero(RList vec, String fsep) { return RDataFactory.createEmptyStringVector(); } @Specialization(guards = "!lengthZero(args)") - protected RStringVector doFilePath(RList args, RAbstractStringVector fsepVec) { + @TruffleBoundary + protected RStringVector doFilePath(RList args, String fsep) { Object[] argValues = args.getDataWithoutCopying(); int resultLength = 0; for (int i = 0; i < argValues.length; i++) { @@ -775,19 +815,24 @@ public class FileFunctions { String[] result = new String[resultLength]; String[][] inputs = new String[argValues.length][]; for (int i = 0; i < argValues.length; i++) { - Object elem = argValues[i]; - if (!(elem instanceof String || elem instanceof RStringVector)) { - elem = initCastStringNode().executeString(elem); + Object elem = args.getDataAt(i); + if (elem instanceof RTypedValue && ((RTypedValue) elem).isS4()) { + throw RError.nyi(this, "list files: S4 elem"); + } else if (elem instanceof RSymbol) { + inputs[i] = new String[]{((RSymbol) elem).getName()}; + } else { + if (!(elem instanceof String || elem instanceof RStringVector)) { + elem = initCastStringNode().executeString(elem); + } } if (elem instanceof String) { inputs[i] = new String[]{(String) elem}; } else if (elem instanceof RStringVector) { inputs[i] = ((RStringVector) elem).getDataWithoutCopying(); } else { - RInternalError.shouldNotReachHere(); + throw RError.error(this, RError.Message.NON_STRING_ARG_TO_INTERNAL_PASTE); } } - String fsep = fsepVec.getDataAt(0); for (int i = 0; i < resultLength; i++) { String path = ""; for (int j = 0; j < inputs.length; j++) { @@ -826,20 +871,18 @@ public class FileFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.toLogical(2).toLogical(3).toLogical(4).toLogical(5); - } - - private boolean checkLogical(byte value, String name) throws RError { - if (RRuntime.isNA(value)) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, name); - } else { - return RRuntime.fromLogical(value); - } + 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()); } @Specialization @TruffleBoundary - protected RLogicalVector fileCopy(RAbstractStringVector vecFrom, RAbstractStringVector vecTo, byte overwriteArg, byte recursiveArg, byte copyModeArg, byte copyDateArg) { + protected RLogicalVector fileCopy(RAbstractStringVector vecFrom, RAbstractStringVector vecTo, boolean overwrite, boolean recursiveA, boolean copyMode, boolean copyDate) { + boolean recursive = recursiveA; int lenFrom = vecFrom.getLength(); byte[] status = new byte[lenFrom]; if (lenFrom > 0) { @@ -847,22 +890,18 @@ public class FileFunctions { if (lenTo != 1) { throw RError.error(this, RError.Message.INVALID_ARGUMENT, "to"); } - boolean overWrite = checkLogical(overwriteArg, "overwrite"); - boolean recursive = checkLogical(recursiveArg, "recursive"); - boolean copyMode = checkLogical(copyModeArg, "copy.mode"); - boolean copyDate = checkLogical(copyDateArg, "copy.dates"); // Java cannot distinguish copy.mode and copy.dates CopyOption[] copyOptions; if (copyMode || copyDate) { - copyOptions = new CopyOption[overWrite ? 2 : 1]; - copyOptions[overWrite ? 1 : 0] = StandardCopyOption.COPY_ATTRIBUTES; - } else if (overWrite) { + copyOptions = new CopyOption[overwrite ? 2 : 1]; + copyOptions[overwrite ? 1 : 0] = StandardCopyOption.COPY_ATTRIBUTES; + } else if (overwrite) { copyOptions = new CopyOption[1]; } else { copyOptions = new CopyOption[0]; } - if (overWrite) { + if (overwrite) { copyOptions[0] = StandardCopyOption.REPLACE_EXISTING; } FileSystem fileSystem = FileSystems.getDefault(); @@ -899,10 +938,10 @@ public class FileFunctions { } } else { // copy to existing files is skipped unless overWrite - if (!Files.exists(toPath) || overWrite) { + if (!Files.exists(toPath) || overwrite) { /* - * Be careful if toPath is a directory, if empty Java will replace - * it with a plain file, otherwise the copy will fail + * toB Be careful if toPath is a directory, if empty Java will + * replace it with a plain file, otherwise the copy will fail */ if (Files.isDirectory(toPath)) { Path fromFileNamePath = fromPath.getFileName(); @@ -985,6 +1024,11 @@ public class FileFunctions { @RBuiltin(name = "dirname", kind = INTERNAL, parameterNames = {"path"}, behavior = IO) public abstract static class DirName extends XyzNameAdapter { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("path").mustBe(stringValue(), RError.Message.CHAR_VEC_ARGUMENT); + } + @Specialization @TruffleBoundary protected RStringVector doDirName(RAbstractStringVector vec) { @@ -998,6 +1042,12 @@ public class FileFunctions { @RBuiltin(name = "basename", kind = INTERNAL, parameterNames = {"path"}, behavior = IO) public abstract static class BaseName extends XyzNameAdapter { + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("path").mustBe(stringValue(), RError.Message.CHAR_VEC_ARGUMENT); + } + @Specialization @TruffleBoundary protected RStringVector doDirName(RAbstractStringVector vec) { @@ -1014,23 +1064,14 @@ public class FileFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.toLogical(1).toLogical(2); - } - - private boolean checkLogical(byte value, String name) throws RError { - if (RRuntime.isNA(value)) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, name); - } else { - return RRuntime.fromLogical(value); - } + 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()); } @Specialization @TruffleBoundary - protected int doUnlink(RAbstractStringVector vec, byte recursiveArg, byte forceArg) { - @SuppressWarnings("unused") - boolean force = checkLogical(forceArg, "force"); - boolean recursive = checkLogical(recursiveArg, "recursive"); + protected int doUnlink(RAbstractStringVector vec, boolean recursive, @SuppressWarnings("unused") boolean force) { int result = 1; FileSystem fileSystem = FileSystems.getDefault(); for (int i = -0; i < vec.getLength(); i++) { @@ -1087,37 +1128,39 @@ public class FileFunctions { } - @SuppressWarnings("unused") - @Fallback - protected int doUnlink(Object vec, Object recursive, Object force) { - throw RError.nyi(this, "unlink"); - } - - public static boolean simpleArgs(@SuppressWarnings("unused") RAbstractStringVector vec, byte recursive, byte force) { - return recursive == RRuntime.LOGICAL_FALSE && force == RRuntime.LOGICAL_FALSE; - } } @RBuiltin(name = "dir.create", visibility = OFF, kind = INTERNAL, parameterNames = {"path", "showWarnings", "recursive", "mode"}, behavior = IO) public abstract static class DirCreate extends RBuiltinNode { + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("path").mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst(); + casts.arg("showWarnings").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("recursive").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("mode").asIntegerVector().findFirst().mapIf(intNA(), constant(0777)); + } + @Specialization @TruffleBoundary - protected byte dirCreate(RAbstractStringVector pathVec, byte showWarnings, byte recursive, RIntVector octMode) { - boolean ok = true; - if (pathVec.getLength() != 1) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "path"); - } - String path = Utils.tildeExpand(pathVec.getDataAt(0)); - if (RRuntime.fromLogical(recursive)) { - ok = mkparentdirs(new File(path).getAbsoluteFile().getParentFile(), showWarnings, octMode.getDataAt(0)); - } - if (ok) { - ok = mkdir(path, showWarnings, octMode.getDataAt(0)); + protected byte dirCreate(String pathIn, boolean showWarnings, boolean recursive, int octMode) { + boolean ok; + if (RRuntime.isNA(pathIn)) { + ok = false; + } else { + ok = true; + String path = Utils.tildeExpand(pathIn); + if (recursive) { + ok = mkparentdirs(new File(path).getAbsoluteFile().getParentFile(), showWarnings, octMode); + } + if (ok) { + ok = mkdir(path, showWarnings, octMode); + } } return RRuntime.asLogical(ok); } - private boolean mkparentdirs(File file, byte showWarnings, int mode) { + private boolean mkparentdirs(File file, boolean showWarnings, int mode) { if (file.isDirectory()) { return true; } @@ -1131,12 +1174,12 @@ public class FileFunctions { } } - private boolean mkdir(String path, byte showWarnings, int mode) { + private boolean mkdir(String path, boolean showWarnings, int mode) { try { RFFIFactory.getRFFI().getBaseRFFI().mkdir(path, mode); return true; } catch (IOException ex) { - if (RRuntime.fromLogical(showWarnings)) { + if (showWarnings) { RError.warning(this, RError.Message.DIR_CANNOT_CREATE, path); } return false; @@ -1146,6 +1189,11 @@ public class FileFunctions { @RBuiltin(name = "dir.exists", kind = INTERNAL, parameterNames = "paths", behavior = IO) public abstract static class DirExists extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("paths").mustBe(stringValue()).asStringVector(); + } + @Specialization @TruffleBoundary protected RLogicalVector dirExists(RAbstractStringVector pathVec) { @@ -1158,9 +1206,5 @@ public class FileFunctions { return RDataFactory.createLogicalVector(data, RDataFactory.COMPLETE_VECTOR); } - @Fallback - protected RLogicalVector dirExists(@SuppressWarnings("unused") Object pathVec) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "filename"); - } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java index b4fe2e8b935e1c936ffbe19ae0074144856615fa..5cfb52fd805c984aa4d327cd58813867f3bfd328 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java @@ -22,39 +22,64 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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 com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode; -import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNode; -import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNodeGen; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; +import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode; import com.oracle.truffle.r.runtime.RError; 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.ops.UnaryArithmeticFactory; @RBuiltin(name = "floor", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) -public abstract class Floor extends RBuiltinNode { +public abstract class Floor extends UnaryArithmeticBuiltinNode { - public static final UnaryArithmeticFactory FLOOR = FloorArithmetic::new; + public static final UnaryArithmeticFactory FLOOR = FloorNodeGen.create(null); - @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create(); - @Child private UnaryArithmeticNode floor = UnaryArithmeticNodeGen.create(FLOOR, RError.Message.NON_NUMERIC_MATH, RType.Double); + public Floor() { + super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null); + } - @Specialization - protected Object floor(Object value) { - return floor.execute(boxPrimitive.execute(value)); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustNotBeNull(this, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).asDoubleVector(); + } + + @Override + public int op(byte op) { + return op; } - private static final class FloorArithmetic extends Round.RoundArithmetic { + @Override + public int op(int op) { + return op; + } + + @Override + public double op(double op) { + return Math.floor(op); + } - @Override - public double op(double op) { - return Math.floor(op); - } + @Override + protected double opd(double re, double im) { + return op(re); } + + @Override + public RComplex op(double re, double im) { + return RDataFactory.createComplex(op(re), op(im)); + } + + @Specialization + @Override + public Object calculateUnboxed(Object op) { + return super.calculateUnboxed(op); + } + } 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 94b46d38ee991e17127d9781521312069da90276..1a3ba7437b2f57baa748a0ec9ff27f05207886b9 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 @@ -22,12 +22,12 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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.Cached; -import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.VirtualFrame; @@ -56,7 +56,9 @@ public abstract class ForceAndCall extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(0); + casts.arg("n").asIntegerVector().findFirst(); + // TODO other types are possible for FUN that we don't yet handle + casts.arg("FUN").mustBe(instanceOf(RFunction.class), RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); } @Specialization(guards = "cachedN == n") @@ -105,9 +107,4 @@ public abstract class ForceAndCall extends RBuiltinNode { throw RError.nyi(this, "generic case of forceAndCall"); } - @SuppressWarnings("unused") - @Fallback - protected Object forceAndCall(Object n, Object fun, RArgsValuesAndNames args) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); - } } 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 4c19c57467c5d72fba300c0e7de12c60c089e866..13749fcbc3c370ec9bc8d607a079f77c1ce63b23 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 @@ -27,6 +27,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; 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.RASTUtils; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; @@ -37,6 +38,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RNull; 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 { @@ -54,6 +56,12 @@ public abstract class Formals extends RBuiltinNode { return createFormals(fun); } + @Fallback + protected Object formals(@SuppressWarnings("unused") Object fun) { + // for anything that is not a function, GnuR returns NULL + return RNull.instance; + } + @TruffleBoundary protected Object createFormals(RFunction fun) { if (fun.isBuiltin()) { @@ -66,7 +74,8 @@ public abstract class Formals extends RBuiltinNode { FormalArguments formalArgs = fdNode.getFormalArguments(); Object succ = RNull.instance; for (int i = formalArgs.getSignature().getLength() - 1; i >= 0; i--) { - Object lang = RASTUtils.createLanguageElement(formalArgs.getDefaultArgument(i)); + RNode argument = formalArgs.getDefaultArgument(i); + Object lang = argument == null ? RSymbol.MISSING : RASTUtils.createLanguageElement(argument.asRSyntaxNode()); RSymbol name = RDataFactory.createSymbol(formalArgs.getSignature().getName(i)); succ = RDataFactory.createPairList(lang, succ, name); } 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 7bd299642def105a42a8605b47f345a551624993..5c9e5594e3badf9d2621198dcece5729469fb97e 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 @@ -11,28 +11,27 @@ */ 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.intNA; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte; +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; 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; 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.ValuePrinterNode; -import com.oracle.truffle.r.nodes.builtin.base.printer.ValuePrinterNodeGen; import com.oracle.truffle.r.nodes.unary.CastIntegerNode; import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; -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.context.RContext; -import com.oracle.truffle.r.runtime.data.RDouble; -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.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; @@ -41,11 +40,12 @@ 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; +@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 { @Child private CastIntegerNode castInteger; - @Child protected ValuePrinterNode valuePrinter = ValuePrinterNodeGen.create(); + @Child protected ValuePrinterNode valuePrinter = new ValuePrinterNode(); protected final BranchProfile errorProfile = BranchProfile.create(); @@ -88,27 +88,27 @@ public abstract class Format extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toVector(1).toLogical(1); - casts.toVector(2).toInteger(2); - casts.toVector(3).toInteger(3); - casts.toVector(4).toInteger(4); - casts.toVector(5).toInteger(5); - casts.toVector(6).toLogical(6); - casts.toVector(7); + casts.arg("x"); + casts.arg("trim").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).notNA().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("scientific").asIntegerVector().findFirst(); + casts.arg("decimal.mark").asStringVector().findFirst(); } @Specialization - protected RStringVector format(RAbstractLogicalVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, - RLogicalVector naEncodeVec, RAbstractVector sciVec, RAbstractStringVector decimalMark) { - checkArgs(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec, decimalMark); - return (RStringVector) valuePrinter.prettyPrint(value, AnyVectorToStringVectorWriter::new); + protected RStringVector format(VirtualFrame frame, RAbstractLogicalVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, + String decimalMark) { + return (RStringVector) valuePrinter.prettyPrint(frame, value, AnyVectorToStringVectorWriter::new); } @Specialization - protected RStringVector format(RAbstractIntVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, - RLogicalVector naEncodeVec, RAbstractVector sciVec, RAbstractStringVector decimalMark) { - checkArgs(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec, decimalMark); - return (RStringVector) valuePrinter.prettyPrint(value, AnyVectorToStringVectorWriter::new); + protected RStringVector format(VirtualFrame frame, RAbstractIntVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, + String decimalMark) { + return (RStringVector) valuePrinter.prettyPrint(frame, value, AnyVectorToStringVectorWriter::new); } // TODO: even though format's arguments are not used at this point, their processing mirrors @@ -134,82 +134,23 @@ public abstract class Format extends RBuiltinNode { } @Specialization - protected RStringVector format(RAbstractDoubleVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, - RLogicalVector naEncodeVec, RAbstractVector sciVec, RAbstractStringVector decimalMark) { - checkArgs(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec, decimalMark); - return (RStringVector) valuePrinter.prettyPrint(value, AnyVectorToStringVectorWriter::new); + protected RStringVector format(VirtualFrame frame, RAbstractDoubleVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, + String decimalMark) { + return (RStringVector) valuePrinter.prettyPrint(frame, value, AnyVectorToStringVectorWriter::new); } @Specialization - protected RStringVector format(RAbstractComplexVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, - RLogicalVector naEncodeVec, RAbstractVector sciVec, RAbstractStringVector decimalMark) { - checkArgs(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec, decimalMark); - return (RStringVector) valuePrinter.prettyPrint(value, AnyVectorToStringVectorWriter::new); - } - - @SuppressWarnings("unused") - private void processArguments(RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec, RAbstractVector sciVec, - RAbstractStringVector decimalMark) { - byte trim = trimVec.getLength() > 0 ? trimVec.getDataAt(0) : RRuntime.LOGICAL_NA; - int digits = digitsVec.getLength() > 0 ? digitsVec.getDataAt(0) : RRuntime.INT_NA; - getConfig().digits = digits; - int nsmall = nsmallVec.getLength() > 0 ? nsmallVec.getDataAt(0) : RRuntime.INT_NA; - int width = widthVec.getLength() > 0 ? widthVec.getDataAt(0) : 0; - int justify = justifyVec.getLength() > 0 ? justifyVec.getDataAt(0) : RRuntime.INT_NA; - byte naEncode = naEncodeVec.getLength() > 0 ? naEncodeVec.getDataAt(0) : RRuntime.LOGICAL_NA; - int sci = computeSciArg(sciVec); - String myOutDec = decimalMark.getDataAt(0); - if (RRuntime.isNA(myOutDec)) { - myOutDec = "."; - } + protected RStringVector format(VirtualFrame frame, RAbstractComplexVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, + String decimalMark) { + return (RStringVector) valuePrinter.prettyPrint(frame, value, AnyVectorToStringVectorWriter::new); } @Specialization - protected RStringVector format(RAbstractStringVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, - RLogicalVector naEncodeVec, RAbstractVector sciVec, RAbstractStringVector decimalMark) { - checkArgs(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec, decimalMark); + 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(); } - // TruffleDSL bug - should not need multiple guards here - protected void checkArgs(RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec, RAbstractVector sciVec, - RAbstractStringVector decimalMark) { - if (trimVec.getLength() > 0 && RRuntime.isNA(trimVec.getDataAt(0))) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "trim"); - } - if (digitsVec.getLength() > 0 && (RRuntime.isNA(digitsVec.getDataAt(0)) || digitsVec.getDataAt(0) < R_MIN_DIGITS_OPT || digitsVec.getDataAt(0) > R_MAX_DIGITS_OPT)) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "digits"); - } - if (nsmallVec.getLength() > 0 && (RRuntime.isNA(nsmallVec.getDataAt(0)) || nsmallVec.getDataAt(0) < 0 || nsmallVec.getDataAt(0) > 20)) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "nsmall"); - } - if (widthVec.getLength() > 0 && RRuntime.isNA(widthVec.getDataAt(0))) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "width"); - } - if (justifyVec.getLength() > 0 && (RRuntime.isNA(justifyVec.getDataAt(0)) || justifyVec.getDataAt(0) < 0 || nsmallVec.getDataAt(0) > 3)) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "justify"); - } - if (naEncodeVec.getLength() > 0 && RRuntime.isNA(naEncodeVec.getDataAt(0))) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "na.encode"); - } - if (sciVec.getLength() != 1 || (sciVec.getElementClass() != RLogical.class && sciVec.getElementClass() != RInteger.class && sciVec.getElementClass() != RDouble.class)) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "scientific"); - } - if (decimalMark.getLength() != 1) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "decmial.mark"); - } - } - - @SuppressWarnings("unused") private static class Config { public int width; public int naWidth; 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 c929d73972986ea4b0ac31e5336b72524325dac2..0ff9871785cb6fb0523d27ae4bae2b6f98f303e7 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 @@ -24,10 +24,8 @@ 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.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -@RBuiltin(name = "formatC", kind = INTERNAL, parameterNames = {"x", "mode", "width", "digits", "format", "flat", "i.strlen"}, behavior = PURE) +@RBuiltin(name = "formatC", kind = INTERNAL, parameterNames = {"x", "mode", "width", "digits", "format", "flag", "i.strlen"}, behavior = PURE) public abstract class FormatC extends RBuiltinNode { @Child private CastStringNode castStringNode; @@ -35,20 +33,25 @@ public abstract class FormatC extends RBuiltinNode { private RStringVector castStringVector(Object o) { if (castStringNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - castStringNode = insert(CastStringNodeGen.create(true, true, true, false)); + castStringNode = insert(CastStringNodeGen.create(true, true, true)); } return (RStringVector) ((RStringVector) castStringNode.executeString(o)).copyDropAttributes(); } @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(2).toInteger(3).toInteger(6); + casts.arg("x"); + casts.arg("mode").asStringVector().findFirst(); + casts.arg("width").asIntegerVector().findFirst(); + casts.arg("digits").asIntegerVector().findFirst(); + casts.arg("format").asStringVector().findFirst(); + casts.arg("flag").asStringVector().findFirst(); + casts.arg("i.strlen").asIntegerVector().findFirst(); } @SuppressWarnings("unused") @Specialization - RAttributable formatC(RAbstractContainer x, RAbstractStringVector modeVec, RAbstractIntVector widthVec, RAbstractIntVector digitsVec, RAbstractStringVector formatVec, - RAbstractStringVector flagVec, RAbstractIntVector iStrlen) { + RAttributable formatC(RAbstractContainer x, String mode, int width, int digits, String format, String flag, int iStrlen) { RStringVector res = castStringVector(x); return res.setClassAttr(null); } 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 b13c52d299ca16817a7bb321921900c47b79d7e5..9737c5b1ff9af48b09cf46788191afdfdd2ec7ac 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 @@ -59,10 +59,10 @@ import com.oracle.truffle.r.runtime.HasSignature; import com.oracle.truffle.r.runtime.RArguments; 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.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; @@ -75,7 +75,6 @@ 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.RPromise.Closure; -import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; import com.oracle.truffle.r.runtime.nodes.RNode; @@ -159,7 +158,7 @@ public class FrameFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.firstIntegerWithError(0, Message.INVALID_ARGUMENT, "which"); + casts.arg("which").asIntegerVector().findFirst(); } @Override @@ -176,8 +175,7 @@ public class FrameFunctions { if (RArguments.getFunction(cframe) == null) { return RNull.instance; } - RLanguage createCall = createCall(RArguments.getCall(cframe)); - return createCall; + return createCall(RArguments.getCall(cframe)); } @TruffleBoundary @@ -209,6 +207,14 @@ public class FrameFunctions { return FrameAccess.READ_ONLY; } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("definition").mustBe(RFunction.class); + casts.arg("call").mustBe(RLanguage.class); + casts.arg("expand.dots").asLogicalVector().findFirst(); + casts.arg("envir").mustBe(REnvironment.class, Message.MUST_BE_ENVIRON); + } + @Specialization protected RLanguage matchCall(RFunction definition, Object callObj, byte expandDotsL, REnvironment env) { /* @@ -281,20 +287,7 @@ public class FrameFunctions { RPairList prev = null; for (int i2 = 0; i2 < varArgNodes.length; i2++) { RNode n = varArgNodes[i2]; - Object listValue; - if (n instanceof ConstantNode) { - listValue = ((ConstantNode) n).getValue(); - } else if (n instanceof ReadVariableNode) { - String id = ((ReadVariableNode) n).getIdentifier(); - assert id == id.intern(); - listValue = RDataFactory.createSymbol(id); - } else if (n instanceof VarArgNode) { - listValue = createVarArgSymbol((VarArgNode) n); - } else if (n instanceof RCallNode) { - listValue = RDataFactory.createLanguage(n); - } else { - throw RInternalError.shouldNotReachHere("node: " + n + " at " + i2); - } + Object listValue = RASTUtils.createLanguageElement(n.asRSyntaxNode()); pl.setCar(listValue); if (varArgSignature.getName(i2) != null) { pl.setTag(RDataFactory.createSymbolInterned(varArgSignature.getName(i2))); @@ -352,12 +345,6 @@ public class FrameFunctions { return false; } - private static RSymbol createVarArgSymbol(VarArgNode varArgNode) { - CompilerAsserts.neverPartOfCompilation(); // for string concatenation and interning - String varArgSymbol = createVarArgName(varArgNode); - return RDataFactory.createSymbolInterned(varArgSymbol); - } - private static String createVarArgName(VarArgNode varArgNode) { CompilerAsserts.neverPartOfCompilation(); // for string concatenation and interning int vn = varArgNode.getIndex() + 1; @@ -424,6 +411,11 @@ public class FrameFunctions { return FrameAccess.MATERIALIZE; } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("which").asIntegerVector().findFirst(); + } + @Specialization protected REnvironment sysFrame(VirtualFrame frame, int which) { REnvironment result; @@ -439,11 +431,6 @@ public class FrameFunctions { return result; } - - @Specialization - protected REnvironment sysFrame(VirtualFrame frame, double which) { - return sysFrame(frame, (int) which); - } } @RBuiltin(name = "sys.frames", kind = INTERNAL, parameterNames = {}, behavior = COMPLEX) @@ -528,7 +515,7 @@ public class FrameFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.firstIntegerWithError(0, Message.INVALID_ARGUMENT, "n"); + casts.arg("n").asIntegerVector().findFirst(); } @Specialization @@ -560,6 +547,11 @@ public class FrameFunctions { return FrameAccess.READ_ONLY; } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("which").asIntegerVector().findFirst(); + } + @Specialization protected Object sysFunction(VirtualFrame frame, int which) { // N.B. Despite the spec, n==0 is treated as the current function @@ -572,11 +564,6 @@ public class FrameFunctions { return func; } } - - @Specialization - protected Object sysFunction(VirtualFrame frame, double which) { - return sysFunction(frame, (int) which); - } } @RBuiltin(name = "sys.parents", kind = INTERNAL, parameterNames = {}, behavior = COMPLEX) @@ -630,11 +617,11 @@ public class FrameFunctions { private final BranchProfile promiseProfile = BranchProfile.create(); private final BranchProfile nonNullCallerProfile = BranchProfile.create(); - public abstract Object execute(VirtualFrame frame, int n); + public abstract REnvironment execute(VirtualFrame frame, int n); @Override protected void createCasts(CastBuilder casts) { - casts.firstIntegerWithError(0, Message.INVALID_VALUE, "n"); + casts.arg("n").asIntegerVector().findFirst(); } @Override @@ -686,10 +673,5 @@ public class FrameFunctions { // } return REnvironment.frameToEnvironment(getNumberedFrame(frame, call.getDepth()).materialize()); } - - @Specialization - protected REnvironment parentFrame(VirtualFrame frame, double n) { - return parentFrame(frame, (int) n); - } } } 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 977dadd9b36be16b65c0ca63acd22ac2c6dfd601..4f5573978e11e9fcb57bc9e72ca495c8d375f30d 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 @@ -22,29 +22,42 @@ */ 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.builtins.RBehavior.COMPLEX; 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.CastBuilder; 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.RDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; @RBuiltin(name = "gc", kind = INTERNAL, parameterNames = {"verbose", "reset"}, behavior = COMPLEX) public abstract class Gc extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("verbose").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("reset").asLogicalVector().findFirst().map(toBoolean()); + } + @SuppressWarnings("unused") @Specialization - protected RDoubleVector gc(RAbstractLogicalVector verbose, RAbstractLogicalVector reset) { - System.gc(); + protected RDoubleVector gc(boolean verbose, boolean reset) { + doGc(); // 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/GetFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java index 81d4ba97e495193b6a14d90228fa3747042825ba..5e425c311184a247df5571b212574eb7980f1cc3 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 @@ -22,6 +22,14 @@ */ 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.chain; +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.stringValue; +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; @@ -31,12 +39,9 @@ import com.oracle.truffle.api.dsl.Cached; 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.api.nodes.Node; 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.CallInlineCacheNode; -import com.oracle.truffle.r.nodes.CallInlineCacheNodeGen; import com.oracle.truffle.r.nodes.RRootNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.attributes.TypeFromModeNode; @@ -46,17 +51,19 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.FormalArguments; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.nodes.function.RCallerHelper; -import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; +import com.oracle.truffle.r.nodes.function.call.CallRFunctionCachedNode; +import com.oracle.truffle.r.nodes.function.call.CallRFunctionCachedNodeGen; import com.oracle.truffle.r.nodes.objects.GetS4DataSlot; import com.oracle.truffle.r.nodes.objects.GetS4DataSlotNodeGen; +import com.oracle.truffle.r.nodes.unary.CastNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; 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.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.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.RFunction; @@ -64,9 +71,9 @@ 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.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.env.REnvironment.Function; /** * assert: not expected to be fast even when called as, e.g., {@code get("x")}. @@ -75,25 +82,26 @@ public class GetFunctions { public abstract static class Adapter extends RBuiltinNode { private final BranchProfile unknownObjectErrorProfile = BranchProfile.create(); protected final ValueProfile modeProfile = ValueProfile.createIdentityProfile(); - protected final BranchProfile inheritsProfile = BranchProfile.create(); + protected final BranchProfile recursiveProfile = BranchProfile.create(); @Child private PromiseHelperNode promiseHelper = new PromiseHelperNode(); @Child protected TypeFromModeNode typeFromMode = TypeFromModeNodeGen.create(); - public abstract Object execute(VirtualFrame frame, Object name, REnvironment envir, String mode, byte inherits); + @CompilationFinal private boolean firstExecution = true; protected void unknownObject(String x, RType modeType, String modeString) throws RError { unknownObjectErrorProfile.enter(); if (modeType == RType.Any) { - throw RError.error(this, RError.Message.UNKNOWN_OBJECT, x); + throw RError.error(RError.SHOW_CALLER, RError.Message.UNKNOWN_OBJECT, x); } else { - throw RError.error(this, RError.Message.UNKNOWN_OBJECT_MODE, x, modeType == null ? modeString : modeType.getName()); + throw RError.error(RError.SHOW_CALLER, RError.Message.UNKNOWN_OBJECT_MODE, x, modeType == null ? modeString : modeType.getName()); } } - protected Object checkPromise(VirtualFrame frame, Object r, String identifier, boolean evaluateOnSlowPath) { + protected Object checkPromise(VirtualFrame frame, Object r, String identifier) { if (r instanceof RPromise) { - if (evaluateOnSlowPath) { - CompilerDirectives.transferToInterpreter(); + if (firstExecution) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + firstExecution = false; return ReadVariableNode.evalPromiseSlowPathWithName(identifier, frame, (RPromise) r); } return promiseHelper.evaluate(frame, (RPromise) r); @@ -102,59 +110,54 @@ public class GetFunctions { } } - protected static boolean isInherits(byte inherits) { - return inherits == RRuntime.LOGICAL_TRUE; - } - - protected Object getAndCheck(VirtualFrame frame, RAbstractStringVector xv, REnvironment env, RType modeType, boolean fail) throws RError { - String x = xv.getDataAt(0); - Object obj = checkPromise(frame, env.get(x), x, !(env instanceof Function)); + protected Object getAndCheck(VirtualFrame frame, String x, REnvironment env, RType modeType, String modeString, boolean fail) throws RError { + Object obj = checkPromise(frame, env.get(x), x); if (obj != null && RRuntime.checkType(obj, modeType)) { return obj; } else { if (fail) { - unknownObject(x, modeType, modeType.getName()); + unknownObject(x, modeType, modeString); } return null; } } - protected Object getInherits(VirtualFrame frame, RAbstractStringVector xv, REnvironment envir, String mode, boolean fail) { - RType modeType = typeFromMode.execute(mode); - Object r = getAndCheck(frame, xv, envir, modeType, false); + protected Object getInherits(VirtualFrame frame, String x, REnvironment envir, RType modeType, String modeString, boolean fail) { + Object r = getAndCheck(frame, x, envir, modeType, modeString, false); if (r == null) { - inheritsProfile.enter(); - String x = xv.getDataAt(0); + recursiveProfile.enter(); REnvironment env = envir; while (env != REnvironment.emptyEnv()) { env = env.getParent(); if (env != REnvironment.emptyEnv()) { - r = checkPromise(frame, env.get(x), x, !(env instanceof Function)); + r = checkPromise(frame, env.get(x), x); if (r != null && RRuntime.checkType(r, modeType)) { break; } } } if (r == null && fail) { - unknownObject(x, modeType, mode); + unknownObject(x, modeType, modeString); } } return r; } } - public static final class S4ToEnvNode extends Node { + public static final class S4ToEnvNode extends CastNode { @Child private GetS4DataSlot getS4Data = GetS4DataSlotNodeGen.create(RType.Environment); - public REnvironment execute(RS4Object obj) { - assert obj.isS4() : "unexpected non-S4 RS4Object"; - Object value = getS4Data.executeObject(obj); + @Override + public Object execute(Object obj) { + RS4Object s4Obj = (RS4Object) obj; + assert s4Obj.isS4() : "unexpected non-S4 RS4Object"; + Object value = getS4Data.executeObject(s4Obj); if (value == RNull.instance) { CompilerDirectives.transferToInterpreter(); throw RError.error(RError.SHOW_CALLER, Message.USE_NULL_ENV_DEFUNCT); } - return (REnvironment) value; + return value; } } @@ -163,25 +166,37 @@ public class GetFunctions { private final ConditionProfile inheritsProfile = ConditionProfile.createBinaryProfile(); + public abstract Object execute(VirtualFrame frame, String x, REnvironment environment, String mode, boolean inherits); + @Override protected void createCasts(CastBuilder casts) { - casts.firstBoolean(3); + casts.arg("x").mustBe(stringValue()).asStringVector().findFirst(); + 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("mode").mustBe(stringValue()).asStringVector().findFirst(); + casts.arg("inherits").allowNull().asLogicalVector().findFirst().map(toBoolean()); } @Specialization - protected Object get(VirtualFrame frame, RAbstractStringVector xv, REnvironment envir, String mode, boolean inherits) { + public Object get(VirtualFrame frame, String x, REnvironment envir, String mode, boolean inherits) { + RType modeType = typeFromMode.execute(mode); if (inheritsProfile.profile(inherits)) { - return getInherits(frame, xv, envir, mode, true); + return getInherits(frame, x, envir, modeType, mode, true); } else { - RType modeType = typeFromMode.execute(mode); - return getAndCheck(frame, xv, envir, modeType, true); + return getAndCheck(frame, x, envir, modeType, mode, true); } } @Specialization - protected Object get(VirtualFrame frame, RAbstractStringVector xv, RS4Object envir, String mode, boolean inherits, // + public Object get(VirtualFrame frame, String x, RS4Object s4Envir, String mode, boolean inherits, @Cached("new()") S4ToEnvNode s4ToEnv) { - return get(frame, xv, s4ToEnv.execute(envir), mode, inherits); + return get(frame, x, (REnvironment) s4ToEnv.execute(s4Envir), mode, inherits); + } + + @SuppressWarnings("unused") + @Specialization + protected Object get(VirtualFrame frame, String x, int envir, String mode, boolean inherits) { + throw RInternalError.unimplemented(); } } @@ -192,17 +207,21 @@ public class GetFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.firstBoolean(3); + casts.arg("x").mustBe(stringValue()).asStringVector().findFirst(); + 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("mode").mustBe(stringValue()).asStringVector().findFirst(); + casts.arg("inherits").allowNull().asLogicalVector().findFirst().map(toBoolean()); } @Specialization - protected Object get0(VirtualFrame frame, RAbstractStringVector xv, REnvironment envir, String mode, boolean inherits, Object ifnotfound) { + protected Object get0(VirtualFrame frame, String x, REnvironment envir, String mode, boolean inherits, Object ifnotfound) { Object result; + RType modeType = typeFromMode.execute(mode); if (inheritsProfile.profile(inherits)) { - result = getInherits(frame, xv, envir, mode, false); + result = getInherits(frame, x, envir, modeType, mode, false); } else { - RType modeType = typeFromMode.execute(mode); - result = getAndCheck(frame, xv, envir, modeType, false); + result = getAndCheck(frame, x, envir, modeType, mode, false); } if (result == null) { result = ifnotfound; @@ -211,9 +230,15 @@ public class GetFunctions { } @Specialization - protected Object get0(VirtualFrame frame, RAbstractStringVector xv, RS4Object envir, String mode, boolean inherits, Object ifnotfound, // + protected Object get0(VirtualFrame frame, String x, RS4Object s4Envir, String mode, boolean inherits, Object ifnotfound, @Cached("new()") S4ToEnvNode s4ToEnv) { - return get0(frame, xv, s4ToEnv.execute(envir), mode, inherits, ifnotfound); + return get0(frame, x, (REnvironment) s4ToEnv.execute(s4Envir), mode, inherits, ifnotfound); + } + + @SuppressWarnings("unused") + @Specialization + protected Object get(VirtualFrame frame, String x, int envir, String mode, boolean inherits, Object ifnotfound) { + throw RInternalError.unimplemented(); } } @@ -223,11 +248,20 @@ public class GetFunctions { private final BranchProfile wrongLengthErrorProfile = BranchProfile.create(); @Child private TypeFromModeNode typeFromMode = TypeFromModeNodeGen.create(); - @Child private CallInlineCacheNode callCache = CallInlineCacheNodeGen.create(); - @Child private RArgumentsNode argsNode; + @Child private CallRFunctionCachedNode callCache = CallRFunctionCachedNodeGen.create(2); @CompilationFinal private boolean needsCallerFrame; + @Override + protected void createCasts(CastBuilder casts) { + 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("mode").mustBe(stringValue()).asStringVector(); + casts.arg("ifnotfound").mustBe(RAbstractListVector.class); + casts.arg("inherits").asLogicalVector().findFirst().map(toBoolean()); + } + private static class State { final int svLength; final int modeLength; @@ -273,56 +307,55 @@ public class GetFunctions { throw RError.error(this, RError.Message.WRONG_LENGTH_ARG, "ifnotfound"); } return state; - } - @Specialization(guards = "!isInherits(inherits)") - protected RList mgetNonInherit(VirtualFrame frame, RAbstractStringVector xv, REnvironment env, RAbstractStringVector mode, RList ifNotFound, @SuppressWarnings("unused") byte inherits) { - State state = checkArgs(xv, mode, ifNotFound); - for (int i = 0; i < state.svLength; i++) { - String x = state.checkNA(xv.getDataAt(i)); - state.names[i] = x; - RType modeType = typeFromMode.execute(mode.getDataAt(state.modeLength == 1 ? 0 : i)); - Object r = checkPromise(frame, env.get(x), x, !(env instanceof Function)); - if (r != null && RRuntime.checkType(r, modeType)) { - state.data[i] = r; - } else { - doIfNotFound(frame, state, i, x, ifNotFound); - } - } - return state.getResult(); - } - - @Specialization(guards = "isInherits(inherits)") - protected RList mgetInherit(VirtualFrame frame, RAbstractStringVector xv, REnvironment envir, RAbstractStringVector mode, RList ifNotFound, @SuppressWarnings("unused") byte inherits) { + @Specialization + protected RList mget(VirtualFrame frame, RAbstractStringVector xv, REnvironment envir, RAbstractStringVector mode, RList ifNotFound, boolean inherits, + @Cached("createBinaryProfile()") ConditionProfile inheritsProfile) { State state = checkArgs(xv, mode, ifNotFound); for (int i = 0; i < state.svLength; i++) { String x = state.checkNA(xv.getDataAt(i)); state.names[i] = x; RType modeType = typeFromMode.execute(mode.getDataAt(state.modeLength == 1 ? 0 : i)); - Object r = envir.get(x); - if (r == null || !RRuntime.checkType(r, modeType)) { - inheritsProfile.enter(); - REnvironment env = envir; - while (env != REnvironment.emptyEnv()) { - env = env.getParent(); - if (env != REnvironment.emptyEnv()) { - r = checkPromise(frame, env.get(x), x, !(env instanceof Function)); - if (r != null && RRuntime.checkType(r, modeType)) { - break; + if (inheritsProfile.profile(inherits)) { + Object r = envir.get(x); + if (r == null || !RRuntime.checkType(r, modeType)) { + recursiveProfile.enter(); + REnvironment env = envir; + while (env != REnvironment.emptyEnv()) { + env = env.getParent(); + if (env != REnvironment.emptyEnv()) { + r = checkPromise(frame, env.get(x), x); + if (r != null && RRuntime.checkType(r, modeType)) { + break; + } } } } - } - if (r == null) { - doIfNotFound(frame, state, i, x, ifNotFound); + if (r == null) { + doIfNotFound(frame, state, i, x, ifNotFound); + } else { + state.data[i] = r; + } } else { - state.data[i] = r; + Object r = checkPromise(frame, envir.get(x), x); + if (r != null && RRuntime.checkType(r, modeType)) { + state.data[i] = r; + } else { + doIfNotFound(frame, state, i, x, ifNotFound); + } } } return state.getResult(); } + @Specialization + protected RList mget(VirtualFrame frame, RAbstractStringVector xv, RS4Object s4Envir, RAbstractStringVector mode, RList ifNotFound, boolean inherits, + @Cached("createBinaryProfile()") ConditionProfile inheritsProfile, + @Cached("new()") S4ToEnvNode s4ToEnv) { + return mget(frame, xv, (REnvironment) s4ToEnv.execute(s4Envir), mode, ifNotFound, inherits, inheritsProfile); + } + private void doIfNotFound(VirtualFrame frame, State state, int i, String x, RList ifNotFound) { if (state.ifnFunc != null) { state.data[i] = call(frame, state.ifnFunc, x); @@ -336,15 +369,11 @@ public class GetFunctions { CompilerDirectives.transferToInterpreterAndInvalidate(); needsCallerFrame = true; } - if (argsNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - argsNode = insert(RArgumentsNode.create()); - } MaterializedFrame callerFrame = needsCallerFrame ? frame.materialize() : null; FormalArguments formals = ((RRootNode) ifnFunc.getRootNode()).getFormalArguments(); RArgsValuesAndNames args = new RArgsValuesAndNames(new Object[]{x}, ArgumentsSignature.empty(1)); - Object[] callArgs = argsNode.execute(ifnFunc, RCaller.create(frame, RCallerHelper.createFromArguments(ifnFunc, args)), callerFrame, new Object[]{x}, formals.getSignature(), null); - return callCache.execute(frame, ifnFunc.getTarget(), callArgs); + return callCache.execute(frame, ifnFunc, RCaller.create(frame, RCallerHelper.createFromArguments(ifnFunc, args)), callerFrame, new Object[]{x}, formals.getSignature(), + ifnFunc.getEnclosingFrame(), null); } } } 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 6af408b6bee5e99998275a8270665da738a59c83..be2ae78d8794067dda33480979066cf13f8a8322 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 @@ -38,7 +38,7 @@ public abstract class GetText extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { casts.arg("domain").asStringVector().findFirst(""); - casts.arg("args").asStringVector(); + casts.arg("args").allowNull().asStringVector(); } @Specialization 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 f36dcf3633f70c228f60ac3fcd56f68dd2341ae4..fd868f0d0d96cfaf558de82a801429364cef12bc 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,6 +11,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -24,6 +25,7 @@ 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.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; @@ -32,10 +34,11 @@ import com.oracle.truffle.r.runtime.RegExp; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; 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.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.RAbstractStringVector; import com.oracle.truffle.r.runtime.ffi.PCRERFFI; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; @@ -64,6 +67,48 @@ public class GrepFunctions { */ protected final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + protected void castPattern(CastBuilder 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 void castText(CastBuilder casts, String textId) { + casts.arg(textId).mustBe(stringValue(), RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, textId); + } + + protected void castIgnoreCase(CastBuilder casts) { + casts.arg("ignore.case").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); + } + + protected void castPerl(CastBuilder casts) { + casts.arg("perl").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); + } + + protected void castFixed(CastBuilder casts, byte defaultValue) { + casts.arg("fixed").asLogicalVector().findFirst(defaultValue); + } + + protected void castValue(CastBuilder casts) { + casts.arg("value").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); + } + + protected void castUseBytes(CastBuilder casts) { + casts.arg("useBytes").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); + } + + protected void castInvert(CastBuilder casts) { + casts.arg("invert").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); + } + + protected void castCosts(CastBuilder casts) { + casts.arg("costs").asIntegerVector(); + } + + protected void castBounds(CastBuilder casts) { + casts.arg("bounds").asDoubleVector(); + } + /** * Temporary method that handles the check for the arguments that are common to the majority * of the functions, that we don't yet implement. If any of the arguments are {@code true}, @@ -267,9 +312,21 @@ public class GrepFunctions { } } - @RBuiltin(name = "grep", kind = INTERNAL, parameterNames = {"pattern", "x", "ignore.case", "perl", "value", "fixed", "useBytes", "invert"}, behavior = PURE) + @RBuiltin(name = "grep", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "value", "perl", "fixed", "useBytes", "invert"}, behavior = PURE) public abstract static class Grep extends GrepAdapter { + @Override + protected void createCasts(CastBuilder casts) { + castPattern(casts); + castText(casts, "text"); + castIgnoreCase(casts); + castValue(casts); + castPerl(casts); + castFixed(casts, RRuntime.LOGICAL_FALSE); + castUseBytes(casts); + castInvert(casts); + } + @Specialization @TruffleBoundary protected Object grepValueFalse(RAbstractStringVector patternArgVec, RAbstractStringVector vector, byte ignoreCaseLogical, byte valueLogical, byte perlLogical, byte fixedLogical, @@ -278,9 +335,21 @@ public class GrepFunctions { } } - @RBuiltin(name = "grepl", kind = INTERNAL, parameterNames = {"pattern", "x", "ignore.case", "value", "perl", "fixed", "useBytes", "invert"}, behavior = PURE) + @RBuiltin(name = "grepl", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "value", "perl", "fixed", "useBytes", "invert"}, behavior = PURE) public abstract static class GrepL extends GrepAdapter { + @Override + protected void createCasts(CastBuilder casts) { + castPattern(casts); + castText(casts, "text"); + castIgnoreCase(casts); + castValue(casts); + castPerl(casts); + castFixed(casts, RRuntime.LOGICAL_FALSE); + castUseBytes(casts); + castInvert(casts); + } + @Specialization @TruffleBoundary protected Object grepl(RAbstractStringVector patternArgVec, RAbstractStringVector vector, byte ignoreCaseLogical, byte valueLogical, byte perlLogical, byte fixedLogical, byte useBytes, @@ -292,6 +361,12 @@ public class GrepFunctions { protected abstract static class SubAdapter extends CommonCodeAdapter { + protected void castReplacement(CastBuilder 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 RStringVector doSub(RAbstractStringVector patternArgVec, RAbstractStringVector replacementVec, RAbstractStringVector vector, byte ignoreCaseLogical, byte perlLogical, byte fixedLogical, @SuppressWarnings("unused") byte useBytes, boolean gsub) { try { @@ -540,9 +615,20 @@ public class GrepFunctions { } } - @RBuiltin(name = "sub", kind = INTERNAL, parameterNames = {"pattern", "replacement", "x", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE) + @RBuiltin(name = "sub", kind = INTERNAL, parameterNames = {"pattern", "replacement", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE) public abstract static class Sub extends SubAdapter { + @Override + protected void createCasts(CastBuilder casts) { + castPattern(casts); + castReplacement(casts); + castText(casts, "text"); + castIgnoreCase(casts); + castPerl(casts); + castFixed(casts, RRuntime.LOGICAL_FALSE); + castUseBytes(casts); + } + @Specialization @TruffleBoundary protected RStringVector subRegexp(RAbstractStringVector patternArgVec, RAbstractStringVector replacementVec, RAbstractStringVector x, byte ignoreCaseLogical, byte perlLogical, @@ -551,9 +637,20 @@ public class GrepFunctions { } } - @RBuiltin(name = "gsub", kind = INTERNAL, parameterNames = {"pattern", "replacement", "x", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE) + @RBuiltin(name = "gsub", kind = INTERNAL, parameterNames = {"pattern", "replacement", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE) public abstract static class GSub extends SubAdapter { + @Override + protected void createCasts(CastBuilder casts) { + castPattern(casts); + castReplacement(casts); + castText(casts, "text"); + castIgnoreCase(casts); + castPerl(casts); + castFixed(casts, RRuntime.LOGICAL_FALSE); + castUseBytes(casts); + } + @Specialization @TruffleBoundary protected RStringVector gsub(RAbstractStringVector patternArgVec, RAbstractStringVector replacementVec, RAbstractStringVector x, byte ignoreCaseLogical, byte perlLogical, byte fixedLogical, @@ -565,6 +662,26 @@ public class GrepFunctions { @RBuiltin(name = "regexpr", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE) public abstract static class Regexp extends CommonCodeAdapter { + @Override + protected void createCasts(CastBuilder casts) { + castPattern(casts); + castText(casts, "text"); + castIgnoreCase(casts); + castPerl(casts); + castFixed(casts, RRuntime.LOGICAL_FALSE); + castUseBytes(casts); + } + + protected static final class IndexAndSize { + protected int index; + protected int size; + + public IndexAndSize(int index, int size) { + this.index = index; + this.size = size; + } + } + @Specialization @TruffleBoundary protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, byte ignoreCaseL, byte perlL, byte fixedL, byte useBytesL) { @@ -572,34 +689,45 @@ public class GrepFunctions { boolean ignoreCase = RRuntime.fromLogical(ignoreCaseL); String pattern = RegExp.checkPreDefinedClasses(patternArg.getDataAt(0)); int[] result = new int[vector.getLength()]; + int[] matchLength = new int[vector.getLength()]; for (int i = 0; i < vector.getLength(); i++) { - result[i] = findIndex(pattern, vector.getDataAt(i), ignoreCase, fixedL == RRuntime.LOGICAL_TRUE).get(0); + IndexAndSize res = findIndexAndSize(pattern, vector.getDataAt(i), ignoreCase, fixedL == RRuntime.LOGICAL_TRUE).get(0); + result[i] = res.index; + matchLength[i] = res.size; } - // TODO attribute as per spec - return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR); + // TODO useBytes attribute as per spec + RIntVector ret = RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR); + ret.setAttr("match.length", RDataFactory.createIntVector(matchLength, RDataFactory.COMPLETE_VECTOR)); + return ret; } - protected static List<Integer> findIndex(String pattern, String text, boolean ignoreCase, boolean fixed) { - List<Integer> list = new ArrayList<>(); + protected static List<IndexAndSize> findIndexAndSize(String pattern, String text, boolean ignoreCase, boolean fixed) { + List<IndexAndSize> list = new ArrayList<>(); if (fixed) { - int index; - if (ignoreCase) { - index = text.toLowerCase().indexOf(pattern.toLowerCase()); - } else { - index = text.indexOf(pattern); + int index = 0; + while (true) { + if (ignoreCase) { + index = text.toLowerCase().indexOf(pattern.toLowerCase(), index); + } else { + index = text.indexOf(pattern, index); + } + if (index == -1) { + break; + } + list.add(new IndexAndSize(index + 1, pattern.length())); + index += pattern.length(); } - list.add(index == -1 ? index : index + 1); } else { Matcher m = getPatternMatcher(pattern, text, ignoreCase); while (m.find()) { // R starts counting at index 1 - list.add(m.start() + 1); - } - if (list.size() > 0) { - return list; + list.add(new IndexAndSize(m.start() + 1, m.end() - m.start())); } - list.add(-1); } + if (list.size() > 0) { + return list; + } + list.add(new IndexAndSize(-1, -1)); return list; } @@ -612,6 +740,16 @@ public class GrepFunctions { @RBuiltin(name = "gregexpr", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE) public abstract static class Gregexpr extends Regexp { + @Override + protected void createCasts(CastBuilder casts) { + castPattern(casts); + castText(casts, "text"); + castIgnoreCase(casts); + castPerl(casts); + castFixed(casts, RRuntime.LOGICAL_FALSE); + castUseBytes(casts); + } + @Specialization @TruffleBoundary @Override @@ -622,29 +760,47 @@ public class GrepFunctions { boolean fixed = RRuntime.fromLogical(fixedL); Object[] result = new Object[vector.getLength()]; for (int i = 0; i < vector.getLength(); i++) { - int[] data = toIntArray(findIndex(pattern, vector.getDataAt(i), ignoreCase, fixed)); - result[i] = RDataFactory.createIntVector(data, RDataFactory.COMPLETE_VECTOR); - // TODO attributes as per spec + List<IndexAndSize> l = findIndexAndSize(pattern, vector.getDataAt(i), ignoreCase, fixed); + int[] indexes = toIndexOrSizeArray(l, true); + int[] sizes = toIndexOrSizeArray(l, false); + RIntVector res = RDataFactory.createIntVector(indexes, RDataFactory.COMPLETE_VECTOR); + res.setAttr("match.length", RDataFactory.createIntVector(sizes, RDataFactory.COMPLETE_VECTOR)); + result[i] = res; + // TODO useBytes attributes as per spec } return RDataFactory.createList(result); } - private static int[] toIntArray(List<Integer> list) { + private static int[] toIndexOrSizeArray(List<IndexAndSize> list, boolean index) { int[] arr = new int[list.size()]; for (int i = 0; i < list.size(); i++) { - arr[i] = list.get(i); + IndexAndSize res = list.get(i); + arr[i] = index ? res.index : res.size; } return arr; } } - @RBuiltin(name = "agrep", kind = INTERNAL, parameterNames = {"pattern", "x", "max.distance", "costs", "ignore.case", "value", "fixed", "useBytes"}, behavior = PURE) + @RBuiltin(name = "agrep", kind = INTERNAL, parameterNames = {"pattern", "x", "ignore.case", "value", "costs", "bounds", "useBytes", "fixed"}, behavior = PURE) public abstract static class AGrep extends CommonCodeAdapter { + @Override + protected void createCasts(CastBuilder casts) { + castPattern(casts); + castText(casts, "x"); + castIgnoreCase(casts); + castValue(casts); + castCosts(casts); + castBounds(casts); + castUseBytes(casts); + castFixed(casts, RRuntime.LOGICAL_TRUE); + } + @SuppressWarnings("unused") @Specialization @TruffleBoundary - protected Object aGrep(RAbstractStringVector patternArg, RAbstractStringVector vector, byte ignoreCase, byte value, RIntVector costs, RDoubleVector bounds, byte useBytes, byte fixed) { + protected Object aGrep(RAbstractStringVector patternArg, RAbstractStringVector vector, byte ignoreCase, byte value, RAbstractIntVector costs, RAbstractDoubleVector bounds, byte useBytes, + byte fixed) { // 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); @@ -742,13 +898,26 @@ public class GrepFunctions { } } - @RBuiltin(name = "agrepl", kind = INTERNAL, parameterNames = {"pattern", "x", "max.distance", "costs", "ignore.case", "fixed", "useBytes"}, behavior = PURE) + @RBuiltin(name = "agrepl", kind = INTERNAL, parameterNames = {"pattern", "x", "ignore.case", "value", "costs", "bounds", "useBytes", "fixed"}, behavior = PURE) public abstract static class AGrepL extends CommonCodeAdapter { + @Override + protected void createCasts(CastBuilder casts) { + castPattern(casts); + castText(casts, "x"); + castIgnoreCase(casts); + castValue(casts); + castCosts(casts); + castBounds(casts); + castUseBytes(casts); + castFixed(casts, RRuntime.LOGICAL_TRUE); + } + @SuppressWarnings("unused") @Specialization @TruffleBoundary - protected Object aGrep(RAbstractStringVector patternArg, RAbstractStringVector vector, byte ignoreCase, RIntVector costs, RDoubleVector bounds, byte useBytes, byte fixed) { + protected Object aGrep(RAbstractStringVector patternArg, RAbstractStringVector vector, byte ignoreCase, byte value, RAbstractIntVector costs, RAbstractDoubleVector bounds, byte useBytes, + byte fixed) { // TODO implement properly, this only supports strict equality! checkExtraArgs(ignoreCase, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, useBytes, RRuntime.LOGICAL_FALSE); byte[] data = new byte[vector.getLength()]; @@ -763,6 +932,15 @@ public class GrepFunctions { @RBuiltin(name = "strsplit", kind = INTERNAL, parameterNames = {"x", "split", "fixed", "perl", "useBytes"}, behavior = PURE) public abstract static class Strsplit extends CommonCodeAdapter { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.NON_CHARACTER); + casts.arg("split").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.NON_CHARACTER); + castFixed(casts, RRuntime.LOGICAL_FALSE); + castPerl(casts); + castUseBytes(casts); + } + private final NACheck na = NACheck.create(); @Specialization 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 95b36bcc700b122afd4a35a94c4be94e0908b7e9..8745ed95dfc3fc2ab44fc5b18bbf7d75b318b088 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 @@ -11,6 +11,8 @@ */ 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.stringValue; 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.RBehavior.PURE; @@ -30,19 +32,15 @@ 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.api.nodes.LoopNode; -import com.oracle.truffle.r.nodes.CallInlineCacheNode; -import com.oracle.truffle.r.nodes.CallInlineCacheNodeGen; 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.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.builtin.base.EvalFunctions.Eval; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.nodes.function.RCallNode; -import com.oracle.truffle.r.nodes.unary.CastIntegerNode; -import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; -import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.nodes.function.call.CallRFunctionCachedNode; +import com.oracle.truffle.r.nodes.function.call.CallRFunctionCachedNodeGen; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RCompression; import com.oracle.truffle.r.runtime.RDeparse; @@ -55,13 +53,11 @@ import com.oracle.truffle.r.runtime.SubstituteVirtualFrame; 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.RDoubleVector; 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.RNull; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RPromise.Closure; @@ -81,17 +77,24 @@ 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", "eenv", "aenv"}, behavior = COMPLEX) + @RBuiltin(name = "makeLazy", visibility = OFF, kind = INTERNAL, parameterNames = {"names", "values", "expr", "eval.env", "assign.env"}, behavior = COMPLEX) public abstract static class MakeLazy extends RBuiltinNode { @Child private Eval eval; private void initEval() { if (eval == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - eval = insert(EvalFunctionsFactory.EvalNodeGen.create(null)); + eval = insert(EvalNodeGen.create(null)); } } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("names").mustBe(stringValue()).asStringVector(); + casts.arg("eval.env").mustBe(instanceOf(REnvironment.class)); + casts.arg("assign.env").mustBe(instanceOf(REnvironment.class)); + } + /** * {@code expr} has the value {@code lazyLoadDBfetch(key, datafile, compressed, envhook)}, * see {@code base/lazyLoad.R}. All the arguments except {@code key} are defined in the @@ -138,8 +141,16 @@ public class HiddenInternalFunctions { * This function copies values of variables from one environment to another environment, * 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) + @RBuiltin(name = "importIntoEnv", kind = INTERNAL, parameterNames = {"impenv", "impnames", "expenv", "expnames"}, behavior = COMPLEX) public abstract static class ImportIntoEnv extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("impenv").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class), RError.Message.BAD_ENVIRONMENT, "import"); + casts.arg("impnames").defaultError(RError.Message.INVALID_ARGUMENT, "names").mustBe(stringValue()).asStringVector(); + casts.arg("expenv").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class), RError.Message.BAD_ENVIRONMENT, "import"); + casts.arg("expnames").defaultError(RError.Message.INVALID_ARGUMENT, "names").mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "names").asStringVector(); + } + @Specialization @TruffleBoundary protected RNull importIntoEnv(REnvironment impEnv, RAbstractStringVector impNames, REnvironment expEnv, RAbstractStringVector expNames) { @@ -161,7 +172,7 @@ public class HiddenInternalFunctions { try { impEnv.put(impsym, binding); } catch (PutException ex) { - throw RError.error(this, ex); + throw RError.error(RError.SHOW_CALLER, ex); } } @@ -175,33 +186,19 @@ public class HiddenInternalFunctions { @RBuiltin(name = "lazyLoadDBfetch", kind = PRIMITIVE, parameterNames = {"key", "datafile", "compressed", "envhook"}, behavior = PURE) public abstract static class LazyLoadDBFetch extends RBuiltinNode { - @Child private CallInlineCacheNode callCache = CallInlineCacheNodeGen.create(); - @Child private CastIntegerNode castIntNode; + @Child private CallRFunctionCachedNode callCache = CallRFunctionCachedNodeGen.create(2); - private void initCast() { - if (castIntNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castIntNode = insert(CastIntegerNodeGen.create(false, false, false)); - } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("compressed").asIntegerVector().findFirst(); } /** * No error checking here as this called by trusted library code. */ @Specialization - protected Object lazyLoadDBFetch(VirtualFrame frame, RIntVector key, RStringVector datafile, RIntVector compressed, RFunction envhook) { - return lazyLoadDBFetchInternal(frame.materialize(), key, datafile, compressed.getDataAt(0), envhook); - } - - @Specialization - protected Object lazyLoadDBFetch(VirtualFrame frame, RIntVector key, RStringVector datafile, RDoubleVector compressed, RFunction envhook) { - return lazyLoadDBFetchInternal(frame.materialize(), key, datafile, (int) compressed.getDataAt(0), envhook); - } - - @Specialization - protected Object lazyLoadDBFetch(VirtualFrame frame, RIntVector key, RStringVector datafile, RLogicalVector compressed, RFunction envhook) { - initCast(); - return lazyLoadDBFetch(frame, key, datafile, castIntNode.doLogicalVector(compressed), envhook); + protected Object lazyLoadDBFetch(VirtualFrame frame, RIntVector key, RStringVector datafile, int compressed, RFunction envhook) { + return lazyLoadDBFetchInternal(frame.materialize(), key, datafile, compressed, envhook); } @TruffleBoundary @@ -256,8 +253,7 @@ public class HiddenInternalFunctions { RSerialize.CallHook callHook = new RSerialize.CallHook() { @Override public Object eval(Object arg) { - Object[] callArgs = RArguments.create(envhook, RCaller.create(frame, getOriginalCall()), null, new Object[]{arg}, null); - return callCache.execute(SubstituteVirtualFrame.create(frame), envhook.getTarget(), callArgs); + return callCache.execute(SubstituteVirtualFrame.create(frame), envhook, RCaller.create(frame, getOriginalCall()), null, new Object[]{arg}, null); } }; String functionName = ReadVariableNode.getSlowPathEvaluationName(); @@ -358,11 +354,12 @@ public class HiddenInternalFunctions { @RBuiltin(name = "lazyLoadDBinsertValue", kind = INTERNAL, parameterNames = {"value", "file", "ascii", "compsxp", "hook"}, behavior = COMPLEX) public abstract static class LazyLoadDBinsertValue extends RBuiltinNode { - @Child private CallInlineCacheNode callCache = CallInlineCacheNodeGen.create(); + @Child private CallRFunctionCachedNode callCache = CallRFunctionCachedNodeGen.create(2); @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(2).toInteger(3); + casts.arg("ascii").asIntegerVector().findFirst(); + casts.arg("compsxp").asIntegerVector().findFirst(); } @Specialization @@ -379,8 +376,7 @@ public class HiddenInternalFunctions { RSerialize.CallHook callHook = new RSerialize.CallHook() { @Override public Object eval(Object arg) { - Object[] callArgs = RArguments.create(hook, RCaller.create(frame, getOriginalCall()), null, new Object[]{arg}, null); - return callCache.execute(SubstituteVirtualFrame.create(frame), hook.getTarget(), callArgs); + return callCache.execute(SubstituteVirtualFrame.create(frame), hook, RCaller.create(frame, getOriginalCall()), null, new Object[]{arg}, null); } }; @@ -454,7 +450,7 @@ public class HiddenInternalFunctions { out.write(cdata); return result; } catch (IOException ex) { - throw RError.error(this, Message.GENERIC, "lazyLoadDBinsertValue file append error"); + throw RError.ioError(this, ex); } } } @@ -462,6 +458,7 @@ public class HiddenInternalFunctions { @RBuiltin(name = "lazyLoadDBflush", kind = INTERNAL, parameterNames = "path", behavior = COMPLEX) public abstract static class LazyLoadDBFlush extends RBuiltinNode { @Specialization + @TruffleBoundary protected RNull doLazyLoadDBFlush(RAbstractStringVector dbPath) { RContext.getInstance().stateLazyDBCache.remove(dbPath.getDataAt(0)); return RNull.instance; 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 9ce81965a3c80242179ecc8c36d2b38cebcf7001..2d1c2f2c6ad9664eedbbc5159ecc3d7cb194ca83 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 @@ -22,11 +22,15 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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.r.nodes.builtin.CastBuilder; 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.RStringVector; @@ -34,6 +38,19 @@ 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 { + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(stringValue(), RError.NO_CALLER, 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("mark").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); + casts.arg("toRaw").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); + + } + @SuppressWarnings("unused") @Specialization protected RStringVector doIConv(RAbstractStringVector x, Object from, Object to, Object sub, byte mark, byte toRaw) { 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 6497ebe1d2c003569da706c433475b68cfa19ae9..7e88547cd7f68abb0d55f4385d5e124e68424154 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 @@ -22,6 +22,7 @@ */ 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.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -41,11 +42,10 @@ import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RAttributes; import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; -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.RLanguage; -import com.oracle.truffle.r.runtime.data.RList; +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; @@ -77,7 +77,11 @@ public abstract class Identical extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.firstBoolean(2, "num.eq").firstBoolean(3, "single.NA").firstBoolean(4, "attrib.as.set").firstBoolean(5, "ignore.bytecode").firstBoolean(6, "ignore.environment"); + casts.arg("num.eq").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + casts.arg("single.NA").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + casts.arg("attrib.as.set").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + casts.arg("ignore.bytecode").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + casts.arg("ignore.environment").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); } private final ConditionProfile vecLengthProfile = ConditionProfile.createBinaryProfile(); @@ -251,7 +255,7 @@ public abstract class Identical extends RBuiltinNode { } @Specialization - protected byte doInternalIdenticalGeneric(RList x, RList y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) { + protected byte doInternalIdenticalGeneric(RListBase x, RListBase y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) { if (x.getLength() != y.getLength()) { return RRuntime.LOGICAL_FALSE; } @@ -347,14 +351,9 @@ public abstract class Identical extends RBuiltinNode { return RRuntime.asLogical(((RConnection) x).getDescriptor() == ((RConnection) y).getDescriptor()); } - @Specialization - protected byte doInternalIdenticalGeneric(RExpression x, RExpression y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) { - return doInternalIdenticalGeneric(x.getList(), y.getList(), numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment); - } - @SuppressWarnings("unused") @Fallback - protected byte doInternalIdenticalWrongTypes(Object x, Object y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) { + 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 { @@ -363,7 +362,7 @@ public abstract class Identical extends RBuiltinNode { } protected boolean vectorsLists(RAbstractVector x, RAbstractVector y) { - return x instanceof RList && y instanceof RList; + return x instanceof RListBase && y instanceof RListBase; } protected boolean argConnections(Object x, Object y) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InfixFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InfixFunctions.java deleted file mode 100644 index a22697f278e1978f7bb11848042eddd7c400fd0f..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InfixFunctions.java +++ /dev/null @@ -1,498 +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.builtin.base; - -import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC; -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; -import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; -import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_FRAME; -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.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.frame.VirtualFrame; -import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.api.profiles.ConditionProfile; -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.builtin.CastBuilder; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.builtin.base.InfixFunctionsFactory.PromiseEvaluatorNodeGen; -import com.oracle.truffle.r.nodes.function.PromiseHelperNode; -import com.oracle.truffle.r.nodes.function.RCallNode; -import com.oracle.truffle.r.nodes.unary.CastListNode; -import com.oracle.truffle.r.nodes.unary.CastListNodeGen; -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.RType; -import com.oracle.truffle.r.runtime.RVisibility; -import com.oracle.truffle.r.runtime.builtins.RBehavior; -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.RLanguage; -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.RPromise; -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.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.RBaseNode; -import com.oracle.truffle.r.runtime.nodes.RNode; -import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; - -/** - * Work-around builtins for infix operators that FastR (currently) does not define as functions. - * These definitions create the illusion that the definitions exist, even if they are not actually - * bound to anything useful. - * - * One important reason that these must exist as {@link RBuiltin}s is that they occur when deparsing - * packages and the deparse logic depends on them being found as builtins. See {@link RDeparse}. - * - */ -public class InfixFunctions { - - @NodeChild(value = "op") - protected abstract static class PromiseEvaluator extends RNode { - - protected PromiseEvaluator create() { - return PromiseEvaluatorNodeGen.create(null); - } - - protected abstract Object execute(VirtualFrame frame, Object op); - - @Specialization(guards = {"!isRPromise(op)", "!isRArgsValuesAndNames(op)"}) - protected Object eval(Object op) { - return op; - } - - @Specialization - protected Object eval(VirtualFrame frame, RPromise p, // - @Cached("new()") PromiseHelperNode promiseHelper) { - return promiseHelper.evaluate(frame, p); - } - - @Specialization(guards = "!args.isEmpty()") - protected RArgsValuesAndNames eval(VirtualFrame frame, RArgsValuesAndNames args, // - @Cached("create()") PromiseEvaluator evalRecursive) { - Object[] values = args.getArguments(); - for (int i = 0; i < values.length; i++) { - values[i] = evalRecursive.execute(frame, values[i]); - } - return args; - } - - @Specialization(guards = "args.isEmpty()") - protected RArgsValuesAndNames evalEmpty(RArgsValuesAndNames args) { - return args; - } - } - - public abstract static class AccessArrayBuiltin extends RBuiltinNode { - - @Child private ExtractVectorNode extractNode; - - @Override - protected void createCasts(CastBuilder casts) { - casts.toLogical(2); - } - - protected abstract boolean isSubset(); - - protected Object access(VirtualFrame frame, Object vector, byte exact, RArgsValuesAndNames inds, Object dropDim) { - if (extractNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - extractNode = insert(ExtractVectorNode.create(isSubset() ? ElementAccessMode.SUBSET : ElementAccessMode.SUBSCRIPT, false)); - } - return extractNode.apply(frame, vector, inds.getArguments(), RLogical.valueOf(exact), dropDim); - } - - protected boolean noInd(RArgsValuesAndNames inds) { - return inds.isEmpty(); - } - } - - @RBuiltin(name = "[", kind = PRIMITIVE, parameterNames = {"x", "...", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE) - public abstract static class AccessArraySubsetBuiltin extends AccessArrayBuiltin { - - @Override - protected boolean isSubset() { - return true; - } - - @SuppressWarnings("unused") - @Specialization - protected RNull get(RNull x, Object inds, Object dropVec) { - return x; - } - - @SuppressWarnings("unused") - @Specialization(guards = "noInd(inds)") - protected Object getNoInd(Object x, RArgsValuesAndNames inds, Object dropVec) { - return x; - } - - @SuppressWarnings("unused") - @Specialization - protected Object get(Object x, RMissing inds, Object dropVec) { - return x; - } - - @Specialization(guards = "!noInd(inds)") - protected Object get(VirtualFrame frame, Object x, RArgsValuesAndNames inds, Object dropVec) { - return access(frame, x, RRuntime.LOGICAL_TRUE, inds, dropVec); - } - } - - @RBuiltin(name = ".subset", kind = PRIMITIVE, parameterNames = {"", "...", "drop"}, behavior = PURE) - public abstract static class AccessArraySubsetDefaultBuiltin { - - } - - @RBuiltin(name = "[[", kind = PRIMITIVE, parameterNames = {"", "...", "exact", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE) - public abstract static class AccessArraySubscriptBuiltin extends AccessArrayBuiltin { - - @Override - protected boolean isSubset() { - return false; - } - - private final ConditionProfile emptyExactProfile = ConditionProfile.createBinaryProfile(); - - @Override - public Object[] getDefaultParameterValues() { - return new Object[]{RMissing.instance, RArgsValuesAndNames.EMPTY, RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_TRUE}; - } - - @SuppressWarnings("unused") - @Specialization - protected RNull getNoInd(RNull x, Object inds, Object exactVec, Object dropVec) { - return x; - } - - @SuppressWarnings("unused") - @Specialization(guards = "noInd(inds)") - protected Object getNoInd(Object x, RArgsValuesAndNames inds, RAbstractLogicalVector exactVec, RAbstractLogicalVector dropVec) { - throw RError.error(this, RError.Message.NO_INDEX); - } - - @SuppressWarnings("unused") - @Specialization - protected Object get(Object x, RMissing inds, RAbstractLogicalVector exactVec, RAbstractLogicalVector dropVec) { - throw RError.error(this, RError.Message.NO_INDEX); - } - - @Specialization(guards = "!noInd(inds)") - protected Object get(VirtualFrame frame, Object x, RArgsValuesAndNames inds, RAbstractLogicalVector exactVec, @SuppressWarnings("unused") RAbstractLogicalVector dropVec) { - /* - * TODO this should not be handled here. The new vector access nodes handle this, remove - * this check as soon as its the default and the old implementation is gone. - */ - byte exact; - if (emptyExactProfile.profile(exactVec.getLength() == 0)) { - exact = RRuntime.LOGICAL_FALSE; - } else { - exact = exactVec.getDataAt(0); - } - return access(frame, x, exact, inds, RRuntime.LOGICAL_TRUE); - } - } - - @RBuiltin(name = ".subset2", kind = PRIMITIVE, parameterNames = {"x", "...", "exact", "drop"}, behavior = PURE) - public abstract static class AccessArraySubscriptDefaultBuiltin { - } - - public abstract static class UpdateArrayBuiltin extends RBuiltinNode { - - @Child private ReplaceVectorNode replaceNode; - - private final ConditionProfile argsLengthLargerThanOneProfile = ConditionProfile.createBinaryProfile(); - - protected Object update(VirtualFrame frame, Object vector, RArgsValuesAndNames args, Object value, boolean isSubset) { - if (replaceNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - replaceNode = insert(ReplaceVectorNode.create(isSubset ? ElementAccessMode.SUBSET : ElementAccessMode.SUBSCRIPT, false)); - } - Object[] pos; - if (argsLengthLargerThanOneProfile.profile(args.getLength() > 1)) { - pos = Arrays.copyOf(args.getArguments(), args.getLength() - 1); - } else { - pos = new Object[]{RMissing.instance}; - } - return replaceNode.apply(frame, vector, pos, value); - } - - @Specialization(guards = "noInd(args)") - @SuppressWarnings("unused") - protected Object getNoInd(Object x, RArgsValuesAndNames args) { - throw RError.error(this, RError.Message.INVALID_ARG_NUMBER, "SubAssignArgs"); - } - - protected boolean noInd(RArgsValuesAndNames args) { - return args.isEmpty(); - } - } - - @RBuiltin(name = "[<-", kind = PRIMITIVE, parameterNames = {"", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE) - public abstract static class UpdateArraySubsetBuiltin extends UpdateArrayBuiltin { - - private static final boolean IS_SUBSET = true; - - @Specialization(guards = "!noInd(args)") - protected Object update(VirtualFrame frame, Object x, RArgsValuesAndNames args) { - Object value = args.getArgument(args.getLength() - 1); - return update(frame, x, args, value, IS_SUBSET); - } - } - - @RBuiltin(name = "[[<-", kind = PRIMITIVE, parameterNames = {"", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE) - public abstract static class UpdateArrayNodeSubscriptBuiltin extends UpdateArrayBuiltin { - - private static final boolean IS_SUBSET = false; - - @Specialization(guards = "!noInd(args)") - protected Object update(VirtualFrame frame, Object x, RArgsValuesAndNames args) { - Object value = args.getArgument(args.getLength() - 1); - return update(frame, x, args, value, IS_SUBSET); - } - } - - @RBuiltin(name = "<-", visibility = RVisibility.OFF, kind = PRIMITIVE, parameterNames = {"x", "i"}, behavior = RBehavior.MODIFIES_FRAME) - public abstract static class AssignBuiltin extends RBuiltinNode { - @SuppressWarnings("unused") - @Specialization - protected Object doIt(Object x, Object i) { - throw RInternalError.unimplemented(); - } - } - - @RBuiltin(name = "=", visibility = RVisibility.OFF, kind = PRIMITIVE, parameterNames = {"x", "i"}, behavior = RBehavior.MODIFIES_FRAME) - public abstract static class AssignBuiltinEq extends RBuiltinNode { - @SuppressWarnings("unused") - @Specialization - protected Object doIt(Object x, Object i) { - throw RInternalError.unimplemented(); - } - } - - @RBuiltin(name = "<<-", visibility = RVisibility.OFF, kind = PRIMITIVE, parameterNames = {"x", "i"}, behavior = COMPLEX) - public abstract static class AssignOuterBuiltin extends RBuiltinNode { - @SuppressWarnings("unused") - @Specialization - protected Object doIt(Object x, Object i) { - throw RInternalError.unimplemented(); - } - } - - @RBuiltin(name = "$", kind = PRIMITIVE, parameterNames = {"", ""}, dispatch = INTERNAL_GENERIC, behavior = PURE) - public abstract static class AccessFieldBuiltin extends RBuiltinNode { - - @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - private final BranchProfile invalidAtomicVector = BranchProfile.create(); - private final BranchProfile error = BranchProfile.create(); - - @Specialization - protected Object access(VirtualFrame frame, Object container, String field) { - if (!(container instanceof RAbstractListVector)) { - invalidAtomicVector.enter(); - if (container instanceof RAbstractVector) { - error.enter(); - throw RError.error(this, RError.Message.DOLLAR_ATOMIC_VECTORS); - } - } - return extract.applyAccessField(frame, container, field); - } - - @Fallback - protected Object fallbackError(@SuppressWarnings("unused") Object container, @SuppressWarnings("unused") Object field) { - throw RError.error(this, RError.Message.INVALID_SUBSCRIPT_TYPE, RType.Language.getName()); - } - } - - @RBuiltin(name = "$<-", kind = PRIMITIVE, parameterNames = {"", "", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE) - public abstract static class UpdateFieldBuiltin extends RBuiltinNode { - - private final BranchProfile coerceList = BranchProfile.create(); - @Child private ReplaceVectorNode extract = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - @Child private CastListNode castList; - - @Specialization - protected Object update(VirtualFrame frame, Object container, String field, Object value) { - Object updatedObject = container; - if (!(container instanceof RAbstractListVector)) { - coerceList.enter(); - updatedObject = coerceList(container, updatedObject); - } - return extract.apply(frame, updatedObject, new Object[]{field}, value); - } - - private Object coerceList(Object object, Object vector) { - Object updatedVector = vector; - if (object instanceof RAbstractVector) { - if (castList == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castList = insert(CastListNodeGen.create(true, true, false)); - } - RError.warning(this, RError.Message.COERCING_LHS_TO_LIST); - updatedVector = castList.executeList(vector); - } - return updatedVector; - } - - @Fallback - protected Object fallbackError(@SuppressWarnings("unused") Object container, Object field, @SuppressWarnings("unused") Object value) { - // TODO: the error message is not quite correct for all types; - // for example: x<-list(a=7); `$<-`(x, c("a"), 42);) - throw RError.error(this, RError.Message.INVALID_SUBSCRIPT_TYPE, RRuntime.classToString(field.getClass())); - } - } - - @RBuiltin(name = "{", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) - public abstract static class BraceBuiltin extends RBuiltinNode { - @SuppressWarnings("unused") - @Specialization - protected Object doIt(Object x) { - throw RInternalError.unimplemented(); - } - } - - @RBuiltin(name = "(", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) - public abstract static class ParenBuiltin extends RBuiltinNode { - @SuppressWarnings("unused") - @Specialization - protected Object doIt(Object x) { - throw RInternalError.unimplemented(); - } - } - - /** - * This a rather strange function. It is where, in GnuR, that the "formula" class is set and the - * ".Environment" attribute on the "call". N.B. the "response" can be missing, which is actually - * handled by an evaluated argument of type {@link RMissing}, although it appears as if the - * "model" argument is missing, i.e. {@code ~ x} result in {@code `~`(x)}. - */ - @RBuiltin(name = "~", kind = PRIMITIVE, parameterNames = {"x", "y"}, nonEvalArgs = {0, 1}, behavior = READS_FRAME) - public abstract static class TildeBuiltin extends RBuiltinNode { - private static final RStringVector FORMULA_CLASS = RDataFactory.createStringVectorFromScalar(RRuntime.FORMULA_CLASS); - - @Override - public Object[] getDefaultParameterValues() { - return new Object[]{RMissing.instance, RMissing.instance}; - } - - @Specialization - protected RLanguage tilde(VirtualFrame frame, RPromise response, @SuppressWarnings("unused") RMissing model) { - return doTilde(frame, null, ((RNode) response.getRep()).asRSyntaxNode()); - } - - @Specialization - protected RLanguage tilde(VirtualFrame frame, RPromise response, RPromise model) { - return doTilde(frame, ((RNode) response.getRep()).asRSyntaxNode(), ((RNode) model.getRep()).asRSyntaxNode()); - } - - private RLanguage doTilde(VirtualFrame frame, @SuppressWarnings("unused") RSyntaxNode response, @SuppressWarnings("unused") RSyntaxNode model) { - RCallNode call = (RCallNode) ((RBaseNode) getParent()).asRSyntaxNode(); - RLanguage lang = RDataFactory.createLanguage(call); - lang.setClassAttr(FORMULA_CLASS); - REnvironment env = REnvironment.frameToEnvironment(frame.materialize()); - lang.setAttr(RRuntime.DOT_ENVIRONMENT, env); - return lang; - } - } - - @RBuiltin(name = "if", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) - public abstract static class IfBuiltin extends RBuiltinNode { - @SuppressWarnings("unused") - @Specialization - protected Object doIt(Object x) { - throw RInternalError.unimplemented(); - } - } - - @RBuiltin(name = "while", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) - public abstract static class WhileBuiltin extends RBuiltinNode { - @SuppressWarnings("unused") - @Specialization - protected Object doIt(Object x) { - throw RInternalError.unimplemented(); - } - } - - @RBuiltin(name = "repeat", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) - public abstract static class RepeatBuiltin extends RBuiltinNode { - @SuppressWarnings("unused") - @Specialization - protected Object doIt(Object x) { - throw RInternalError.unimplemented(); - } - } - - @RBuiltin(name = "for", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) - public abstract static class ForBuiltin extends RBuiltinNode { - @SuppressWarnings("unused") - @Specialization - protected Object doIt(Object x) { - throw RInternalError.unimplemented(); - } - } - - @RBuiltin(name = "break", kind = PRIMITIVE, parameterNames = {"x"}, behavior = COMPLEX) - public abstract static class BreakBuiltin extends RBuiltinNode { - @SuppressWarnings("unused") - @Specialization - protected Object doIt(Object x) { - throw RInternalError.unimplemented(); - } - } - - @RBuiltin(name = "next", kind = PRIMITIVE, parameterNames = {"x"}, behavior = COMPLEX) - public abstract static class NextBuiltin extends RBuiltinNode { - @SuppressWarnings("unused") - @Specialization - protected Object doIt(Object x) { - throw RInternalError.unimplemented(); - } - } - - @RBuiltin(name = "function", kind = PRIMITIVE, parameterNames = {"x"}, behavior = READS_FRAME) - public abstract static class FunctionBuiltin extends RBuiltinNode { - @SuppressWarnings("unused") - @Specialization - protected Object doIt(Object x) { - throw RInternalError.unimplemented(); - } - } -} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Inherits.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Inherits.java deleted file mode 100644 index b55bcba0c9a18371cc85157f85b6f1867f8f2ae2..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Inherits.java +++ /dev/null @@ -1,98 +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.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.Specialization; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.unary.InheritsNode; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.builtins.RBuiltin; -import com.oracle.truffle.r.runtime.conn.RConnection; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RExternalPtr; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RNull; -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.RAbstractStringVector; -import com.oracle.truffle.r.runtime.env.REnvironment; - -@RBuiltin(name = "inherits", kind = INTERNAL, parameterNames = {"x", "what", "which"}, behavior = PURE) -// TODO inherits is applicable to every type of object, if only because of "try-error". -public abstract class Inherits extends RBuiltinNode { - - public abstract Object execute(Object x, Object what, Object which); - - @Child private InheritsNode inheritsNode; - @Child private Inherits recursiveInherits; - - private InheritsNode initInheritsNode() { - if (inheritsNode == null) { - inheritsNode = insert(com.oracle.truffle.r.nodes.unary.InheritsNodeGen.create()); - } - return inheritsNode; - } - - @SuppressWarnings("unused") - @Specialization - protected Object doesInherit(RNull x, RAbstractStringVector what, byte which) { - return RRuntime.LOGICAL_FALSE; - } - - @Specialization - protected Object doesInherit(REnvironment x, RAbstractStringVector what, byte which) { - return initInheritsNode().executeObject(x, what, which); - } - - @Specialization - protected Object doesInherit(RFunction x, RAbstractStringVector what, byte which) { - return initInheritsNode().executeObject(x, what, which); - } - - @Specialization - protected Object doesInherit(RSymbol x, RAbstractStringVector what, byte which) { - return initInheritsNode().executeObject(x, what, which); - } - - @Specialization - protected Object doesInherit(RConnection x, RAbstractStringVector what, byte which) { - return initInheritsNode().executeObject(x, what, which); - } - - @Specialization - protected Object doesInherit(RAbstractContainer x, RAbstractStringVector what, byte which) { - return initInheritsNode().executeObject(x, what, which); - } - - @Specialization - protected Object doesInherit(RArgsValuesAndNames x, RAbstractStringVector what, byte which) { - assert x.getLength() == 1; - if (recursiveInherits == null) { - recursiveInherits = insert(com.oracle.truffle.r.nodes.builtin.base.InheritsNodeGen.create(null)); - } - return recursiveInherits.execute(x.getArgument(0), what, which); - } - - @Specialization - protected Object doesInherit(RS4Object x, RAbstractStringVector what, byte which) { - return initInheritsNode().executeObject(x, what, which); - } - - @Specialization - protected Object doesInherit(RExternalPtr x, RAbstractStringVector what, byte which) { - return initInheritsNode().executeObject(x, what, which); - } -} 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 new file mode 100644 index 0000000000000000000000000000000000000000..e6c8ec77d4dadf8564670ecbd855c7143a1cf207 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java @@ -0,0 +1,47 @@ +/* + * 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.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.runtime.RError.Message.NOT_CHARACTER_VECTOR; +import static com.oracle.truffle.r.runtime.RError.Message.NOT_LEN_ONE_LOGICAL_VECTOR; +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.r.nodes.builtin.CastBuilder; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.unary.InheritsNode; +import com.oracle.truffle.r.nodes.unary.InheritsNodeGen; +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 { + + @Child InheritsNode inheritsNode = InheritsNodeGen.create(); + + public abstract Object execute(Object x, Object what, Object which); + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("what").mustBe(stringValue(), NOT_CHARACTER_VECTOR, "what"); + casts.arg("which").mustBe(logicalValue(), NOT_LEN_ONE_LOGICAL_VECTOR, "which").asLogicalVector().findFirst().map(toBoolean()); + } + + @Specialization + protected Object doesInherit(Object x, RAbstractStringVector what, boolean which) { + return inheritsNode.executeObject(x, what, which); + } +} 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 716c189e58f9d9785db54cc5469e3eed7a7d332f..9b65d700b6a7e99b15d7b2ac17a87b9af8f28c56 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 @@ -39,7 +39,7 @@ public abstract class IntToBits extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(0); + casts.arg("x").allowNull().asIntegerVector(); } @Specialization 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 70c4b5fc8a83da31212e59bb0a3142756f4f6a41..23a2a3bc064f3b8ce1c8608eeab0b9f7b682918f 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 @@ -113,8 +113,9 @@ public abstract class Internal extends RBuiltinNode { return false; } + // TODO check this; it is out of date private static final String[] NOT_IMPLEMENTED = new String[]{ - ".addTryHandlers", "interruptsSuspended", "restart", "backsolve", "max.col", "row", "all.names", "comment", "`comment<-`", "list2env", "tcrossprod", "setFileTime", "lbeta", + ".addTryHandlers", "interruptsSuspended", "restart", "backsolve", "max.col", "row", "all.names", "comment", "`comment<-`", "list2env", "tcrossprod", "lbeta", "beta", "lchoose", "choose", "dchisq", "pchisq", "qchisq", "dexp", "pexp", "qexp", "dgeom", "pgeom", "qgeom", "dpois", "ppois", "qpois", "dt", "pt", "qt", "dsignrank", "psignrank", "qsignrank", "besselJ", "besselY", "psigamma", "dbeta", "pbeta", "qbeta", "dbinom", "pbinom", "qbinom", "dcauchy", "pcauchy", "qcauchy", "df", "pf", "qf", "dgamma", "pgamma", "qgamma", "dlnorm", "plnorm", "qlnorm", "dlogis", "plogis", "qlogis", "dnbinom", "pnbinom", "qnbinom", "dnorm", "pnorm", "qnorm", "dunif", "punif", "qunif", "dweibull", 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 600bd243f8c58edbf75aea4ee69c0de38f84427d..32634f340058a8195c16d16ee6dea96c987d8017 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,6 +29,7 @@ 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.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; @@ -82,6 +83,7 @@ public class IsFiniteFunctions { @Fallback protected Object doIsFiniteOther(Object x) { if (typeofNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); typeofNode = insert(TypeofNodeGen.create()); } String type = typeofNode.execute(x).getName(); 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 5d105cad8443d6c8cbcd9eb94e212c96e0526df7..ef9753318c478405b2f7b1117a6d6228cbc0876f 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 @@ -10,6 +10,7 @@ */ 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.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -71,7 +72,7 @@ public abstract class IsListFactor extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.firstBoolean(1); + casts.arg("recursive").asLogicalVector().findFirst().map(toBoolean()); } protected static IsListFactorInternal createNode(boolean recursive) { 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 c1800d0e0d80ad7f2a92b45960cb682f4cedceac..a8deae7653b779140448579f75fcb0f1d4f6b75e 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 @@ -28,7 +28,9 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.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.RRuntime; @@ -37,16 +39,16 @@ import com.oracle.truffle.r.runtime.data.RAttributeProfiles; 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.RFunction; -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.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.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.RAbstractVector; @RBuiltin(name = "is.na", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE) public abstract class IsNA extends RBuiltinNode { @@ -54,6 +56,7 @@ public abstract class IsNA extends RBuiltinNode { @Child private IsNA recursiveIsNA; private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + private final ConditionProfile nullDimNamesProfile = ConditionProfile.createBinaryProfile(); private Object isNARecursive(Object o) { if (recursiveIsNA == null) { @@ -76,7 +79,7 @@ public abstract class IsNA extends RBuiltinNode { for (int i = 0; i < vector.getLength(); i++) { resultVector[i] = RRuntime.asLogical(RRuntime.isNA(vector.getDataAt(i))); } - return RDataFactory.createLogicalVector(resultVector, RDataFactory.COMPLETE_VECTOR, vector.getDimensions(), vector.getNames(attrProfiles)); + return createResult(resultVector, vector); } @Specialization @@ -90,7 +93,7 @@ public abstract class IsNA extends RBuiltinNode { for (int i = 0; i < vector.getLength(); i++) { resultVector[i] = RRuntime.asLogical(RRuntime.isNAorNaN(vector.getDataAt(i))); } - return RDataFactory.createLogicalVector(resultVector, RDataFactory.COMPLETE_VECTOR, vector.getDimensions(), vector.getNames(attrProfiles)); + return createResult(resultVector, vector); } @Specialization @@ -100,7 +103,7 @@ public abstract class IsNA extends RBuiltinNode { RComplex complex = vector.getDataAt(i); resultVector[i] = RRuntime.asLogical(RRuntime.isNAorNaN(complex.getRealPart()) || RRuntime.isNAorNaN(complex.getImaginaryPart())); } - return RDataFactory.createLogicalVector(resultVector, RDataFactory.COMPLETE_VECTOR, vector.getDimensions(), vector.getNames(attrProfiles)); + return createResult(resultVector, vector); } @Specialization @@ -114,7 +117,7 @@ public abstract class IsNA extends RBuiltinNode { for (int i = 0; i < vector.getLength(); i++) { resultVector[i] = RRuntime.asLogical(RRuntime.isNA(vector.getDataAt(i))); } - return RDataFactory.createLogicalVector(resultVector, RDataFactory.COMPLETE_VECTOR, vector.getDimensions(), vector.getNames(attrProfiles)); + return createResult(resultVector, vector); } @Specialization @@ -154,7 +157,7 @@ public abstract class IsNA extends RBuiltinNode { for (int i = 0; i < vector.getLength(); i++) { resultVector[i] = (RRuntime.isNA(vector.getDataAt(i)) ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE); } - return RDataFactory.createLogicalVector(resultVector, RDataFactory.COMPLETE_VECTOR, vector.getDimensions(), vector.getNames(attrProfiles)); + return createResult(resultVector, vector); } @Specialization @@ -173,7 +176,7 @@ public abstract class IsNA extends RBuiltinNode { for (int i = 0; i < vector.getLength(); i++) { resultVector[i] = RRuntime.LOGICAL_FALSE; } - return RDataFactory.createLogicalVector(resultVector, RDataFactory.COMPLETE_VECTOR, vector.getDimensions(), vector.getNames(attrProfiles)); + return createResult(resultVector, vector); } @Specialization @@ -182,15 +185,20 @@ public abstract class IsNA extends RBuiltinNode { return RDataFactory.createEmptyLogicalVector(); } - @Specialization - protected byte isNA(RLanguage value) { - RError.warning(this, RError.Message.IS_NA_TO_NON_VECTOR, value.getRType().getName()); + // Note: all the primitive values have specialization, so we can only get RTypedValue in + // fallback + @Fallback + protected byte isNA(Object value) { + RError.warning(this, RError.Message.IS_NA_TO_NON_VECTOR, ((RTypedValue) value).getRType().getName()); return RRuntime.LOGICAL_FALSE; } - @Specialization - protected byte isNA(RFunction value) { - RError.warning(this, RError.Message.IS_NA_TO_NON_VECTOR, value.getRType().getName()); - return RRuntime.LOGICAL_FALSE; + private RLogicalVector createResult(byte[] data, RAbstractVector originalVector) { + RLogicalVector result = RDataFactory.createLogicalVector(data, RDataFactory.COMPLETE_VECTOR, originalVector.getDimensions(), originalVector.getNames(attrProfiles)); + RList dimNames = originalVector.getDimNames(attrProfiles); + if (nullDimNamesProfile.profile(dimNames != null)) { + result.setDimNames(dimNames); + } + return result; } } 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 2d10974c2f2cd5be2a516cc84e5e1df3201ff6d1..82458154281a76cb2b7d6b71a4e48a5471be5e55 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 @@ -22,6 +22,8 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +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.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -29,9 +31,9 @@ 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.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.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode; import com.oracle.truffle.r.runtime.RError; @@ -46,7 +48,7 @@ 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.RList; -import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RListBase; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RRaw; @@ -66,21 +68,13 @@ import com.oracle.truffle.r.runtime.nodes.RNode; @SuppressWarnings("unused") public class IsTypeFunctions { - protected abstract static class ErrorAdapter extends RBuiltinNode { - protected final BranchProfile errorProfile = BranchProfile.create(); + protected abstract static class MissingAdapter extends RBuiltinNode { - protected RError missingError() throws RError { - errorProfile.enter(); - throw RError.error(this, RError.Message.ARGUMENT_MISSING, "x"); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").conf(c -> c.allowNull().mustNotBeMissing(null, RError.Message.ARGUMENT_MISSING, "x")); } - } - - protected abstract static class MissingAdapter extends ErrorAdapter { - @Specialization - protected byte isType(RMissing value) throws RError { - throw missingError(); - } } @RBuiltin(name = "is.array", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) @@ -107,18 +101,18 @@ public class IsTypeFunctions { return RRuntime.LOGICAL_FALSE; } - @Specialization(guards = "!isListVector(arg)") + @Specialization(guards = {"!isRList(arg)", "!isRExpression(arg)"}) protected byte isRecursive(RAbstractVector arg) { return RRuntime.LOGICAL_FALSE; } @Specialization - protected byte isRecursive(RList arg) { + protected byte isRecursive(RListBase arg) { return RRuntime.LOGICAL_TRUE; } protected boolean isListVector(RAbstractVector arg) { - return arg instanceof RList; + return arg instanceof RListBase; } @Fallback @@ -137,14 +131,14 @@ public class IsTypeFunctions { return RRuntime.LOGICAL_TRUE; } - @Specialization(guards = "!isRList(arg)") + @Specialization(guards = {"!isRList(arg)", "!isRExpression(arg)"}) protected byte isAtomic(RAbstractVector arg) { return RRuntime.LOGICAL_TRUE; } protected static boolean isNonListVector(Object value) { return value instanceof Integer || value instanceof Double || value instanceof RComplex || value instanceof String || value instanceof RRaw || - (value instanceof RAbstractVector && !(value instanceof RList)); + (value instanceof RAbstractVector && !(value instanceof RListBase)); } protected boolean isFactor(Object value) { @@ -476,21 +470,22 @@ public class IsTypeFunctions { } @RBuiltin(name = "is.vector", kind = INTERNAL, parameterNames = {"x", "mode"}, behavior = PURE) - public abstract static class IsVector extends ErrorAdapter { + public abstract static class IsVector extends RBuiltinNode { private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").conf(c -> c.allowNull().mustNotBeMissing(null, RError.Message.ARGUMENT_MISSING, "x")); + casts.arg("mode").defaultError(this, RError.Message.INVALID_ARGUMENT, "mode").mustBe(stringValue()).asStringVector().mustBe(size(1)); + } + @Override public Object[] getDefaultParameterValues() { // INTERNAL does not need default parameters return RNode.EMPTY_OBJECT_ARRAY; } - @Specialization - protected byte isVector(RMissing value, String mode) { - throw missingError(); - } - @Specialization protected byte isVector(RAbstractVector x, String mode) { if (!namesOnlyOrNoAttr(x) || !modeIsAnyOrMatches(x, mode)) { 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 827a48a9edae5c1acb6085e7a02e1a243b5ce150..e6a3136fd669d1216274ebdb47c9d99d25b85a73 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 @@ -22,16 +22,26 @@ */ 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.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.Fallback; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.binary.BinaryMapBooleanFunctionNode; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.base.Order.CmpNode; +import com.oracle.truffle.r.nodes.builtin.base.OrderNodeGen.CmpNodeGen; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RRaw; +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.ops.BinaryCompare; @@ -41,14 +51,28 @@ import com.oracle.truffle.r.runtime.ops.BinaryCompare; public abstract class IsUnsorted extends RBuiltinNode { @Child private BinaryMapBooleanFunctionNode ge = new BinaryMapBooleanFunctionNode(BinaryCompare.GREATER_EQUAL.create()); + @Child private BinaryMapBooleanFunctionNode gt = new BinaryMapBooleanFunctionNode(BinaryCompare.GREATER_THAN.create()); + + private final ConditionProfile strictlyProfile = ConditionProfile.createBinaryProfile(); + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("strictly").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).notNA().map(toBoolean()); + } @Specialization - protected byte isUnsorted(RAbstractDoubleVector x, @SuppressWarnings("unused") byte strictly) { + protected byte isUnsorted(RAbstractDoubleVector x, boolean strictly) { double last = x.getDataAt(0); for (int k = 1; k < x.getLength(); k++) { double current = x.getDataAt(k); - if (ge.applyLogical(current, last) == RRuntime.LOGICAL_FALSE) { - return RRuntime.LOGICAL_TRUE; + if (strictlyProfile.profile(strictly)) { + if (ge.applyLogical(last, current) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } + } else { + if (gt.applyLogical(last, current) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } } last = current; } @@ -56,12 +80,18 @@ public abstract class IsUnsorted extends RBuiltinNode { } @Specialization - protected byte isUnsorted(RAbstractIntVector x, @SuppressWarnings("unused") byte strictly) { + protected byte isUnsorted(RAbstractIntVector x, boolean strictly) { int last = x.getDataAt(0); for (int k = 1; k < x.getLength(); k++) { int current = x.getDataAt(k); - if (ge.applyLogical(current, last) == RRuntime.LOGICAL_FALSE) { - return RRuntime.LOGICAL_TRUE; + if (strictlyProfile.profile(strictly)) { + if (ge.applyLogical(last, current) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } + } else { + if (gt.applyLogical(last, current) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } } last = current; } @@ -69,15 +99,69 @@ public abstract class IsUnsorted extends RBuiltinNode { } @Specialization - protected byte isUnsorted(RAbstractStringVector x, @SuppressWarnings("unused") byte strictly) { + protected byte isUnsorted(RAbstractStringVector x, boolean strictly) { String last = x.getDataAt(0); for (int k = 1; k < x.getLength(); k++) { String current = x.getDataAt(k); - if (ge.applyLogical(current, last) == RRuntime.LOGICAL_FALSE) { - return RRuntime.LOGICAL_TRUE; + if (strictlyProfile.profile(strictly)) { + if (ge.applyLogical(last, current) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } + } else { + if (gt.applyLogical(last, current) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } } last = current; } return RRuntime.LOGICAL_FALSE; } + + protected CmpNode createCmpNode() { + return CmpNodeGen.create(); + } + + @Specialization + protected byte isUnsorted(RAbstractRawVector x, boolean strictly) { + RRaw last = x.getDataAt(0); + for (int k = 1; k < x.getLength(); k++) { + RRaw current = x.getDataAt(k); + if (strictlyProfile.profile(strictly)) { + if (ge.applyRaw(last.getValue(), current.getValue()) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } + } else { + if (gt.applyRaw(last.getValue(), current.getValue()) == RRuntime.LOGICAL_TRUE) { + return RRuntime.LOGICAL_TRUE; + } + } + last = current; + } + return RRuntime.LOGICAL_FALSE; + } + + @Specialization + protected byte isUnsorted(RAbstractComplexVector x, boolean strictly, @Cached("createCmpNode()") CmpNode cmpNode) { + int last = 0; + for (int k = 1; k < x.getLength(); k++) { + if (strictlyProfile.profile(strictly)) { + if (cmpNode.ccmp(x, last, k, true) >= 0) { + return RRuntime.LOGICAL_TRUE; + } + } else { + if (cmpNode.ccmp(x, last, k, true) > 0) { + return RRuntime.LOGICAL_TRUE; + } + } + last = k; + } + return RRuntime.LOGICAL_FALSE; + } + + @Fallback + @SuppressWarnings("unused") + protected byte isUnsortedFallback(Object x, Object strictly) { + return RRuntime.LOGICAL_NA; + } + } 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 fbca3bc8b730b5ae713741b793487dd8408090cd..e36efcd23f30aee4e3a34d8c3cf91c65e5e07833 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 @@ -11,13 +11,23 @@ */ 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.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.matrix; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.not; +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; +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; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; +import java.util.function.Function; + import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; 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.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; @@ -37,8 +47,6 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; 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.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; @@ -70,23 +78,21 @@ public class LaFunctions { private final ConditionProfile hasComplexValues = ConditionProfile.createBinaryProfile(); private final BranchProfile errorProfile = BranchProfile.create(); + @Override + protected void createCasts(CastBuilder casts) { + 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()); + } + @Specialization - protected Object doRg(RDoubleVector matrix, byte onlyValues) { - if (!matrix.isMatrix()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.MUST_BE_SQUARE_NUMERIC, "x"); - } + protected Object doRg(RDoubleVector matrix, boolean onlyValues) { int[] dims = matrix.getDimensions(); - if (onlyValues == RRuntime.LOGICAL_NA) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "only.values"); - } // copy array component of matrix as Lapack destroys it int n = dims[0]; double[] a = matrix.getDataCopy(); char jobVL = 'N'; char jobVR = 'N'; - boolean vectors = onlyValues == RRuntime.LOGICAL_FALSE; + boolean vectors = !onlyValues; if (vectors) { // TODO fix RError.nyi(this, "\"only.values == FALSE\""); @@ -122,7 +128,7 @@ public class LaFunctions { break; } } - RVector values = null; + RVector<?> values = null; Object vectorValues = RNull.instance; if (hasComplexValues.profile(complexValues)) { double[] data = new double[n * 2]; @@ -154,13 +160,14 @@ public class LaFunctions { private final BranchProfile errorProfile = BranchProfile.create(); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("in").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a"); + } + @Specialization - protected RList doQr(RAbstractVector aIn) { + protected RList doQr(RAbstractDoubleVector aIn) { // This implementation is sufficient for B25 matcal-5. - if (!aIn.isMatrix()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.MUST_BE_NUMERIC_MATRIX, "a"); - } if (!(aIn instanceof RDoubleVector)) { RError.nyi(this, "non-real vectors not supported (yet)"); } @@ -209,15 +216,12 @@ public class LaFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.toDouble(1, false, true, false); + casts.arg("q").mustBe(instanceOf(RList.class)); + casts.arg("b").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "b"); } @Specialization protected RDoubleVector doQrCoefReal(RList qIn, RDoubleVector bIn) { - if (!bIn.isMatrix()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.MUST_BE_NUMERIC_MATRIX, "b"); - } // If bIn was coerced this extra copy is unnecessary RDoubleVector b = (RDoubleVector) bIn.copy(); @@ -273,22 +277,28 @@ public class LaFunctions { private final ConditionProfile infoGreaterZero = ConditionProfile.createBinaryProfile(); private final ConditionProfile doUseLog = ConditionProfile.createBinaryProfile(); + @Override + protected void createCasts(CastBuilder casts) { + //@formatter:off + 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("uselog").defaultError(RError.Message.MUST_BE_LOGICAL, "logarithm"). + asLogicalVector(). + findFirst(). + notNA(). + map(toBoolean()); + //@formatter:on + } + @Specialization - protected RList doDetGeReal(RDoubleVector aIn, byte useLogIn) { - if (!aIn.isMatrix()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.MUST_BE_NUMERIC_MATRIX, "a"); - } + protected RList doDetGeReal(RDoubleVector aIn, boolean useLog) { RDoubleVector a = (RDoubleVector) aIn.copy(); int[] aDims = aIn.getDimensions(); int n = aDims[0]; - if (n != aDims[1]) { - errorProfile.enter(); - throw RError.error(this, RError.Message.MUST_BE_SQUARE_MATRIX, "a"); - } int[] ipiv = new int[n]; double modulus = 0; - boolean useLog = RRuntime.fromLogical(useLogIn); double[] aData = a.getDataWithoutCopying(); int info = RFFIFactory.getRFFI().getLapackRFFI().dgetrf(n, n, aData, n, ipiv); int sign = 1; @@ -326,7 +336,7 @@ public class LaFunctions { } } RDoubleVector modulusVec = RDataFactory.createDoubleVectorFromScalar(modulus); - modulusVec.setAttr("logarithm", useLogIn); + modulusVec.setAttr("logarithm", RRuntime.asLogical(useLog)); RList result = RDataFactory.createList(new Object[]{modulusVec, sign}, NAMES_VECTOR); RVector.setVectorClassAttr(result, DET_CLASS); return result; @@ -339,20 +349,30 @@ public class LaFunctions { private final BranchProfile errorProfile = BranchProfile.create(); private final ConditionProfile noPivot = ConditionProfile.createBinaryProfile(); + @Override + protected void createCasts(CastBuilder casts) { + //@formatter:off + 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("pivot").asLogicalVector(). + findFirst(). + notNA(). + map(toBoolean()); + + casts.arg("tol").asDoubleVector(). + findFirst(RRuntime.DOUBLE_NA); + //@formatter:on + } + @Specialization - protected RDoubleVector doDetGeReal(RDoubleVector aIn, byte pivot, double tol) { + protected RDoubleVector doDetGeReal(RDoubleVector aIn, boolean piv, double tol) { RDoubleVector a = (RDoubleVector) aIn.copy(); int[] aDims = aIn.getDimensions(); int n = aDims[0]; int m = aDims[1]; - if (n != m) { - errorProfile.enter(); - throw RError.error(this, RError.Message.MUST_BE_SQUARE_MATRIX, "a"); - } - if (m <= 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.DIMS_GT_ZERO, "a"); - } double[] aData = a.getDataWithoutCopying(); /* zero the lower triangle */ for (int j = 0; j < n; j++) { @@ -360,7 +380,6 @@ public class LaFunctions { aData[i + n * j] = 0; } } - boolean piv = RRuntime.fromLogical(pivot); int info; if (noPivot.profile(!piv)) { info = RFFIFactory.getRFFI().getLapackRFFI().dpotrf('U', m, aData, m); @@ -379,7 +398,7 @@ public class LaFunctions { // TODO informative error message (aka GnuR) throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dpotrf"); } - a.setAttr("pivot", pivot); + a.setAttr("pivot", RRuntime.asLogical(piv)); a.setAttr("rank", rank[0]); RList dn = a.getDimNames(); if (dn != null && dn.getDataAt(0) != null) { @@ -400,18 +419,27 @@ public class LaFunctions { protected final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); @Child private CastDoubleNode castDouble = CastDoubleNodeGen.create(false, false, false); + private static Function<RAbstractDoubleVector, Object> getDimVal(int dim) { + return vec -> vec.getDimensions()[dim]; + } + @Override protected void createCasts(CastBuilder casts) { - casts.toDouble(1, false, true, false); - casts.toDouble(2, false, false, false); + //@formatter:off + 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("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("tolin").asDoubleVector().findFirst(RRuntime.DOUBLE_NA); + //@formatter:on } @Specialization - protected RDoubleVector laSolve(RAbstractVector a, RDoubleVector bin, RAbstractDoubleVector tolin) { - double tol = tolin.getLength() == 0 ? RRuntime.DOUBLE_NA : tolin.getDataAt(0); - if (!(a.isMatrix() && (a instanceof RAbstractDoubleVector || a instanceof RAbstractIntVector || a instanceof RAbstractLogicalVector))) { - throw RError.error(this, RError.Message.MUST_BE_NUMERIC_MATRIX, "a"); - } + protected RDoubleVector laSolve(RAbstractVector a, RDoubleVector bin, double tol) { int[] aDims = a.getDimensions(); int n = aDims[0]; if (n == 0) { @@ -496,10 +524,5 @@ public class LaFunctions { return b; } - @SuppressWarnings("unused") - @Fallback - protected RDoubleVector laSolve(Object a, Object bin, Object tol) { - throw RError.error(this, RError.Message.INCORRECT_ARG); - } } } 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 7d63116162572f6333674e70744eb839b4186d8b..a75fdbb515e1a6c46e2d4a92aedaf3d6a5d9a70a 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 @@ -11,6 +11,7 @@ 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.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -32,14 +33,15 @@ 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.access.vector.ExtractVectorNodeGen; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.LapplyNodeGen.LapplyInternalNodeGen; import com.oracle.truffle.r.nodes.control.RLengthNode; import com.oracle.truffle.r.nodes.function.RCallNode; 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.RSerialize.State; import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -71,6 +73,15 @@ public abstract class Lapply extends RBuiltinNode { @Child private LapplyInternalNode lapply = LapplyInternalNodeGen.create(); + @Override + protected void createCasts(CastBuilder casts) { + // 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); + } + @Specialization protected Object lapply(VirtualFrame frame, RAbstractVector vec, RFunction fun) { Object[] result = lapply.execute(frame, vec, fun); @@ -117,11 +128,6 @@ public abstract class Lapply extends RBuiltinNode { public RSyntaxElement[] getSyntaxArguments() { return new RSyntaxElement[]{RSyntaxLookup.createDummyLookup(LAZY_DEPARSE, "X", false), RSyntaxLookup.createDummyLookup(LAZY_DEPARSE, "i", false)}; } - - @Override - public void serializeImpl(State state) { - throw RInternalError.shouldNotReachHere(); - } } public abstract static class LapplyInternalNode extends RBaseNode implements InternalRSyntaxNodeChildren { @@ -178,6 +184,6 @@ public abstract class Lapply extends RBuiltinNode { } static SourceSection createCallSourceSection() { - return CALL_SOURCE.createSection("", 0, CALL_SOURCE.getLength()); + return CALL_SOURCE.createSection(0, CALL_SOURCE.getLength()); } } 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 c8210163ab4edb2e607186ccfc2685099f23396f..1911c82d4c157a6142f31df3a1b903f2121a5f72 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 @@ -22,23 +22,22 @@ */ 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.numericValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; +import static com.oracle.truffle.r.runtime.RError.Message.INVALID_VALUE; +import static com.oracle.truffle.r.runtime.RError.Message.X_LIST_ATOMIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import java.util.Arrays; 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.frame.VirtualFrame; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.builtin.base.IsTypeFunctions.IsAtomic; -import com.oracle.truffle.r.nodes.builtin.base.IsTypeFunctionsFactory.IsAtomicNodeGen; import com.oracle.truffle.r.nodes.control.RLengthNode; -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.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -50,14 +49,14 @@ 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 { - @Child private IsAtomic isAtomicNode; @Child private RLengthNode lengthNode; private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); @Override protected void createCasts(CastBuilder casts) { - casts.toLogical(1); + 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() { @@ -68,7 +67,7 @@ public abstract class Lengths extends RBuiltinNode { } @Specialization - protected RIntVector doList(VirtualFrame frame, RList list, byte useNames) { + protected RIntVector doList(VirtualFrame frame, RList list, boolean useNames) { initLengthNode(); int[] data = new int[list.getLength()]; for (int i = 0; i < data.length; i++) { @@ -79,32 +78,20 @@ public abstract class Lengths extends RBuiltinNode { } @Specialization - protected RIntVector doNull(@SuppressWarnings("unused") RNull x, @SuppressWarnings("unused") byte useNames) { - return RDataFactory.createIntVectorFromScalar(1); + protected RIntVector doNull(@SuppressWarnings("unused") RNull x, @SuppressWarnings("unused") boolean useNames) { + return RDataFactory.createEmptyIntVector(); } - @Fallback - protected RIntVector doObject(VirtualFrame frame, Object x, Object useNames) { - if (isAtomicNode == null) { - isAtomicNode = insert(IsAtomicNodeGen.create(null)); - } - byte isAtomic = (byte) isAtomicNode.execute(frame, x); - if (!RRuntime.fromLogical(isAtomic)) { - throw RError.error(this, RError.Message.X_LIST_ATOMIC); - } - if (x instanceof RAbstractVector) { - RAbstractVector xa = (RAbstractVector) x; - int[] data = new int[xa.getLength()]; - Arrays.fill(data, 1); - return createResult(xa, data, (byte) useNames); - } else { - throw RInternalError.unimplemented(); - } + @Specialization + protected RIntVector doObject(RAbstractVector xa, boolean useNames) { + int[] data = new int[xa.getLength()]; + Arrays.fill(data, 1); + return createResult(xa, data, useNames); } - private RIntVector createResult(RAbstractVector x, int[] data, byte useNames) { + private RIntVector createResult(RAbstractVector x, int[] data, boolean useNames) { RIntVector result = RDataFactory.createIntVector(data, RDataFactory.COMPLETE_VECTOR); - if (RRuntime.fromLogical(useNames)) { + if (useNames) { result.copyNamesFrom(attrProfiles, x); } return result; 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 bae6feead23e36ad0a1c3a7ba166c502db08338c..e87f6b36855705860fc21fba64a5dc51b231f37f 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 @@ -27,17 +27,24 @@ 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.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.RList2EnvNode; +import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.builtins.RBuiltin; -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; @RBuiltin(name = "list2env", kind = INTERNAL, parameterNames = {"x", "envir"}, behavior = PURE) public abstract class List2Env extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(RAbstractListVector.class, Message.FIRST_ARGUMENT_NOT_NAMED_LIST); + casts.arg("envir").mustBe(REnvironment.class, Message.MUST_BE_ENVIRON, "envir"); + } @Specialization - protected REnvironment doList2Env(RList list, REnvironment env, + protected REnvironment doList2Env(RAbstractListVector list, REnvironment env, @Cached("new()") RList2EnvNode list2Env) { return list2Env.execute(list, env); } 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 0fbc233c6a0b1b27d3a60aa6eec89c1f897b2df1..5f79770abc4bab1dd4eb45e30e926df69022f24c 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 @@ -30,10 +30,9 @@ 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.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.function.opt.ShareObjectNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -41,23 +40,32 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RStringVector; @RBuiltin(name = "list", kind = PRIMITIVE, parameterNames = {"..."}, behavior = PURE) public abstract class ListBuiltin extends RBuiltinNode { protected static final int CACHE_LIMIT = 2; - protected static final int MAX_PROFILES = 16; + protected static final int MAX_SHARE_OBJECT_NODES = 16; - @CompilationFinal private final ValueProfile[] valueProfiles = new ValueProfile[MAX_PROFILES]; + @Children private final ShareObjectNode[] shareObjectNodes = new ShareObjectNode[MAX_SHARE_OBJECT_NODES]; private final ConditionProfile namesNull = ConditionProfile.createBinaryProfile(); - private final BranchProfile shareable = BranchProfile.create(); - private final BranchProfile temporary = BranchProfile.create(); @CompilationFinal private RStringVector suppliedSignatureArgNames; - protected RStringVector argNameVector(ArgumentsSignature signature) { + /** + * Creates a shared permanent vector so that it can be re-used for every list(...) with the same + * arguments. + */ + protected final RStringVector cachedArgNameVector(ArgumentsSignature signature) { + RStringVector result = argNameVector(signature); + if (result != null) { + result.makeSharedPermanent(); + } + return result; + } + + protected final RStringVector argNameVector(ArgumentsSignature signature) { if (namesNull.profile(signature.getNonNullCount() == 0)) { return null; } @@ -66,48 +74,36 @@ public abstract class ListBuiltin extends RBuiltinNode { String orgName = signature.getName(i); names[i] = (orgName == null ? RRuntime.NAMES_ATTR_EMPTY_VALUE : orgName); } - return RDataFactory.createStringVector(names, RDataFactory.COMPLETE_VECTOR); - } - - private void shareListElement(Object value) { - if (value instanceof RShareable) { - shareable.enter(); - if (((RShareable) value).isTemporary()) { - temporary.enter(); - ((RShareable) value).incRefCount(); - } - } + RStringVector result = RDataFactory.createStringVector(names, RDataFactory.COMPLETE_VECTOR); + return result; } /** - * This specialization unrolls the loop that shares the list elements, uses value profiles for - * each element, and keeps a cached version of the name vector. + * This specialization unrolls the loop that shares the list elements, uses a different + * {@link ShareObjectNode} for each element, and keeps a cached version of the name vector. */ @Specialization(limit = "CACHE_LIMIT", guards = {"!args.isEmpty()", // - "args.getLength() <= MAX_PROFILES", // + "args.getLength() <= MAX_SHARE_OBJECT_NODES", // "cachedLength == args.getLength()", // "cachedSignature == args.getSignature()"}) @ExplodeLoop protected RList listCached(RArgsValuesAndNames args, // @Cached("args.getLength()") int cachedLength, // @SuppressWarnings("unused") @Cached("args.getSignature()") ArgumentsSignature cachedSignature, // - @Cached("argNameVector(cachedSignature)") RStringVector cachedArgNames) { + @Cached("cachedArgNameVector(cachedSignature)") RStringVector cachedArgNames) { Object[] argArray = args.getArguments(); for (int i = 0; i < cachedLength; i++) { - if (valueProfiles[i] == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - valueProfiles[i] = ValueProfile.createClassProfile(); - } - shareListElement(valueProfiles[i].profile(argArray[i])); + getShareObjectNode(i).execute(argArray[i]); } return RDataFactory.createList(argArray, cachedArgNames); } @Specialization(guards = "!args.isEmpty()") - protected RList list(RArgsValuesAndNames args) { + protected RList list(RArgsValuesAndNames args, + @Cached("create()") ShareObjectNode shareObjectNode) { Object[] argArray = args.getArguments(); for (int i = 0; i < argArray.length; i++) { - shareListElement(argArray[i]); + shareObjectNode.execute(argArray[i]); } return RDataFactory.createList(argArray, argNameVector(args.getSignature())); } @@ -123,12 +119,21 @@ public abstract class ListBuiltin extends RBuiltinNode { } @Specialization(guards = {"!isRArgsValuesAndNames(value)", "!isRMissing(value)"}) - protected RList listSingleElement(Object value) { - shareListElement(value); + protected RList listSingleElement(Object value, + @Cached("create()") ShareObjectNode shareObjectNode) { + shareObjectNode.execute(value); if (suppliedSignatureArgNames == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); suppliedSignatureArgNames = argNameVector(ArgumentsSignature.empty(1)); } return RDataFactory.createList(new Object[]{value}, suppliedSignatureArgNames); } + + private ShareObjectNode getShareObjectNode(int index) { + if (shareObjectNodes[index] == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + shareObjectNodes[index] = insert(ShareObjectNode.create()); + } + return shareObjectNodes[index]; + } } 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 e61ffdd09d51f9b01e722c6b7b567781c44514dd..1667cb57214e008f159f6c76bb50e95fb9a146a0 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 @@ -12,6 +12,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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; @@ -25,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.frame.VirtualFrame; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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; @@ -38,7 +40,6 @@ 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.RStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.REnvironment.PutException; @@ -53,9 +54,16 @@ public class LoadSaveFunctions { private final NACheck naCheck = NACheck.create(); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("con").mustBe(instanceOf(RConnection.class)); + casts.arg("envir").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class)); + casts.arg("verbose").asLogicalVector().findFirst().map(toBoolean()); + } + @Specialization @TruffleBoundary - protected RStringVector load(RConnection con, REnvironment envir, @SuppressWarnings("unused") RAbstractLogicalVector verbose) { + protected RStringVector load(RConnection con, REnvironment envir, @SuppressWarnings("unused") boolean verbose) { try (RConnection openConn = con.forceOpen("r")) { String s = openConn.readChar(5, true); if (s.equals("RDA2\n") || s.equals("RDB2\n") || s.equals("RDX2\n")) { @@ -91,17 +99,23 @@ public class LoadSaveFunctions { throw RError.error(this, RError.Message.GENERIC, "the input does not start with a magic number compatible with loading from a connection"); } } catch (IOException iox) { - throw RError.error(this, RError.Message.ERROR_READING_CONNECTION, iox.getMessage()); + throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_READING_CONNECTION, iox.getMessage()); } catch (PutException px) { - throw RError.error(this, px); + throw RError.error(RError.SHOW_CALLER, px); } } } - @RBuiltin(name = "load", visibility = OFF, kind = INTERNAL, parameterNames = {"con", "envir"}, behavior = IO) + @RBuiltin(name = "load", visibility = OFF, kind = INTERNAL, parameterNames = {"file", "envir"}, behavior = IO) public abstract static class Load extends RBuiltinNode { // now deprecated but still used by some packages + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("file").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.FIRST_ARGUMENT_NOT_FILENAME).findFirst(); + casts.arg("envir").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class)); + } + private static final int R_MAGIC_EMPTY = 999; private static final int R_MAGIC_CORRUPT = 998; private static final int R_MAGIC_TOONEW = 997; @@ -114,8 +128,8 @@ public class LoadSaveFunctions { @Specialization @TruffleBoundary - protected RStringVector load(RAbstractStringVector fileVec, @SuppressWarnings("unused") REnvironment envir) { - String path = Utils.tildeExpand(fileVec.getDataAt(0)); + protected RStringVector load(String pathIn, @SuppressWarnings("unused") REnvironment envir) { + String path = Utils.tildeExpand(pathIn); try (BufferedInputStream bs = new BufferedInputStream(new FileInputStream(path))) { int magic = readMagic(bs); switch (magic) { @@ -169,16 +183,25 @@ public class LoadSaveFunctions { } } - @RBuiltin(name = "saveToConn", visibility = OFF, kind = INTERNAL, parameterNames = {"list", "conn", "ascii", "version", "envir", "eval.promises"}, behavior = IO) + @RBuiltin(name = "saveToConn", visibility = OFF, kind = INTERNAL, parameterNames = {"list", "con", "ascii", "version", "environment", "eval.promises"}, behavior = IO) public abstract static class SaveToConn extends Adapter { private static final String ASCII_HEADER = "RDA2\n"; private static final String XDR_HEADER = "RDX2\n"; + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("list").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.FIRST_ARGUMENT_NOT_CHARVEC).findFirst(); + casts.arg("con").mustBe(instanceOf(RConnection.class)); + casts.arg("ascii").mustBe(logicalValue(), RError.Message.ASCII_NOT_LOGICAL); + casts.arg("version").allowNull().mustBe(integerValue()); + casts.arg("environment").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class)); + casts.arg("eval.promises").asLogicalVector().findFirst().notNA().map(toBoolean()); + } + @Specialization protected Object saveToConn(VirtualFrame frame, RAbstractStringVector list, RConnection conn, byte asciiLogical, @SuppressWarnings("unused") RNull version, REnvironment envir, - byte evalPromisesLogical, // + boolean evalPromises, // @Cached("new()") PromiseCheckHelperNode promiseHelper) { - boolean evalPromises = RRuntime.fromLogical(evalPromisesLogical); RPairList prev = null; Object toSave = RNull.instance; for (int i = 0; i < list.getLength(); i++) { @@ -191,7 +214,7 @@ public class LoadSaveFunctions { value = promiseHelper.checkEvaluate(frame, value); } RPairList pl = RDataFactory.createPairList(value); - pl.setTag(RDataFactory.createSymbol(varName.intern())); + pl.setTag(RDataFactory.createSymbol(Utils.intern(varName))); if (prev == null) { toSave = pl; } else { 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 c55810944e2010f2a4f0612444b9a2d566b64aef..0e316e77593a9f388daf0fa95bc7ddec0b274daa 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 @@ -22,6 +22,13 @@ */ 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.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; +import static com.oracle.truffle.r.runtime.RError.NO_CALLER; import static com.oracle.truffle.r.runtime.builtins.RBehavior.MODIFIES_STATE; import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -31,6 +38,7 @@ import java.nio.charset.Charset; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; @@ -40,7 +48,6 @@ 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.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; public class LocaleFunctions { @@ -48,11 +55,15 @@ public class LocaleFunctions { @RBuiltin(name = "Sys.getlocale", kind = INTERNAL, parameterNames = {"category"}, behavior = READS_STATE) public abstract static class GetLocale extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.category(casts); + } + @Specialization @TruffleBoundary - protected Object getLocale(RAbstractIntVector categoryVec) { + protected Object getLocale(int category) { // TODO implement all: for now just return not available (NULL) - int category = categoryVec.getDataAt(0); switch (category) { case 3: // "LC_CTYPE", return RDataFactory.createStringVector(Charset.defaultCharset().name()); @@ -82,16 +93,15 @@ public class LocaleFunctions { @RBuiltin(name = "Sys.setlocale", kind = INTERNAL, parameterNames = {"category", "locale"}, behavior = MODIFIES_STATE) public abstract static class SetLocale extends RBuiltinNode { - @Specialization - @TruffleBoundary - protected Object setLocale(@SuppressWarnings("unused") RAbstractIntVector categoryVec, RAbstractStringVector locale) { - // TODO implement properly!! - return locale; + @Override + protected void createCasts(CastBuilder casts) { + Casts.category(casts); + casts.arg("locale").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst(); } @Specialization @TruffleBoundary - protected Object setLocale(@SuppressWarnings("unused") RAbstractIntVector categoryVec, RNull locale) { + protected Object setLocale(@SuppressWarnings("unused") int category, String locale) { // TODO implement properly!! return locale; } @@ -124,6 +134,11 @@ public class LocaleFunctions { @RBuiltin(name = "enc2native", kind = PRIMITIVE, parameterNames = "x", behavior = READS_STATE) public abstract static class Enc2Native extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.xCharacterVector(casts); + } + @Specialization protected Object enc2Native(RAbstractStringVector x) { // TODO implement properly @@ -133,6 +148,11 @@ public class LocaleFunctions { @RBuiltin(name = "enc2utf8", kind = PRIMITIVE, parameterNames = "x", behavior = READS_STATE) public abstract static class Enc2Utf8 extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.xCharacterVector(casts); + } + @Specialization protected Object enc2Native(RAbstractStringVector x) { // TODO implement properly @@ -142,6 +162,11 @@ public class LocaleFunctions { @RBuiltin(name = "bindtextdomain", kind = PRIMITIVE, parameterNames = {"domain", "dirname"}, behavior = READS_STATE) public abstract static class BindTextDomain extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("domain").mustBe(stringValue(), INVALID_VALUE, "domain"); + } + @SuppressWarnings("unused") @Specialization protected RNull bindtextdomain(RAbstractStringVector domain, Object dirname) { @@ -149,4 +174,14 @@ public class LocaleFunctions { return RNull.instance; } } + + private static final class Casts { + private static void xCharacterVector(CastBuilder casts) { + casts.arg("x").mustBe(stringValue(), ARGUMENT_NOT_CHAR_VECTOR); + } + + private static void category(CastBuilder casts) { + casts.arg("category").mustBe(numericValue(), NO_CALLER, 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 bff61b25db30e3bb4a4ccaa3e64619360e00391c..5bf1d9ac7265203e81e5ecf582c584a5c72d04de 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 @@ -22,11 +22,14 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; 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 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.unary.UnaryArithmeticBuiltinNode; @@ -37,14 +40,18 @@ 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.RDoubleVector; -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.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +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 { + private final NAProfile naProfile = NAProfile.create(); + private final BranchProfile nanProfile = BranchProfile.create(); + @Override public Object[] getDefaultParameterValues() { return new Object[]{RMissing.instance, Math.E}; @@ -52,15 +59,8 @@ public class LogFunctions { @Override protected void createCasts(CastBuilder casts) { - // // base argument is at index 1, and double - // arguments[1] = CastDoubleNodeGen.create(arguments[1], true, false, false); - casts.toDouble(1); - } - - @SuppressWarnings("unused") - @Specialization - protected RNull log(RNull x, RNull base) { - throw RError.error(this, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION); + 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(); } @Specialization @@ -74,21 +74,21 @@ public class LogFunctions { } @Specialization - protected RDoubleVector log(RIntVector vector, double base) { + protected RDoubleVector log(RAbstractIntVector vector, double base) { 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 (!RRuntime.isNA(inputValue)) { + if (!naProfile.isNA(inputValue)) { result = logb(inputValue, base); } resultVector[i] = result; } - return RDataFactory.createDoubleVector(resultVector, vector.isComplete()); + return RDataFactory.createDoubleVector(resultVector, vector.isComplete() && !RRuntime.isNA(base)); } @Specialization - protected RDoubleVector log(RDoubleVector vector, double base) { + protected RDoubleVector log(RAbstractDoubleVector vector, double base) { double[] doubleVector = new double[vector.getLength()]; for (int i = 0; i < vector.getLength(); i++) { double value = vector.getDataAt(i); @@ -97,10 +97,19 @@ public class LogFunctions { } doubleVector[i] = value; } - return RDataFactory.createDoubleVector(doubleVector, vector.isComplete()); + return RDataFactory.createDoubleVector(doubleVector, vector.isComplete() && !RRuntime.isNA(base)); } - private static double logb(double x, double base) { + private double logb(double x, double base) { + if (naProfile.isNA(base)) { + return RRuntime.DOUBLE_NA; + } + + if (Double.isNaN(base)) { + nanProfile.enter(); + return base; + } + return Math.log(x) / Math.log(base); } } @@ -114,6 +123,11 @@ public class LogFunctions { private static final double LOG_10 = Math.log(10); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue())); + } + @Override public double op(double op) { return Math.log10(op); @@ -136,6 +150,11 @@ public class LogFunctions { private static final double LOG_2 = Math.log(2); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue())); + } + @Override public double op(double op) { return Math.log(op) / LOG_2; @@ -156,6 +175,11 @@ public class LogFunctions { super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null); } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue())); + } + @Override public int op(byte op) { throw new UnsupportedOperationException(); 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 3f958d27efd911a5ff2df9fc5fe401f197de7a03..c7bd9e803344a24d85f625fac7636dbc4c0a7f11 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 @@ -22,13 +22,16 @@ */ 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.Message.INVALID_ARGUMENT; +import static com.oracle.truffle.r.runtime.RError.NO_CALLER; 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.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.RStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; @@ -36,9 +39,16 @@ 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 { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("envir").mustBe(REnvironment.class, NO_CALLER, INVALID_ARGUMENT, "envir"); + casts.arg("all.names").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("sorted").asLogicalVector().findFirst().map(toBoolean()); + } + @Specialization @TruffleBoundary - protected RStringVector ls(REnvironment envir, byte allNames, byte sorted) { - return envir.ls(RRuntime.fromLogical(allNames), null, RRuntime.fromLogical(sorted)); + protected RStringVector ls(REnvironment envir, boolean allNames, boolean sorted) { + return envir.ls(allNames, null, sorted); } } 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 bba53b2726983cd0c892f65ec4695d5d0e8eaf92..17ff7a961b43aa354e83786301eea5db379826ab 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -30,19 +31,12 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.unary.CastLogicalNode; -import com.oracle.truffle.r.nodes.unary.CastLogicalNodeGen; -import com.oracle.truffle.r.nodes.unary.CastNode; -import com.oracle.truffle.r.nodes.unary.CastToVectorNode; -import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "make.names", kind = INTERNAL, parameterNames = {"names", "allow_"}, behavior = PURE) @@ -53,7 +47,8 @@ public abstract class MakeNames extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.custom(1, new AllowUnderscoreConverter()); + 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()); } @TruffleBoundary @@ -176,38 +171,4 @@ public abstract class MakeNames extends RBuiltinNode { } } - @Specialization(guards = "!wrongAllowUnderscore(allowUnderScoreArg)") - protected RAbstractStringVector makeNames(RAbstractStringVector names, RAbstractLogicalVector allowUnderScoreArg) { - return makeNames(names, allowUnderScoreArg.getDataAt(0)); - } - - @SuppressWarnings("unused") - @Specialization(guards = "wrongAllowUnderscore(allowUnderScoreArg)") - protected RAbstractStringVector makeNamesWrongUnderscoreEmpty(RAbstractStringVector names, RAbstractLogicalVector allowUnderScoreArg) { - throw invalidAllowValue(this); - } - - protected static boolean wrongAllowUnderscore(RAbstractLogicalVector allowUnderScoreArg) { - return allowUnderScoreArg.getLength() == 0 || RRuntime.isNA(allowUnderScoreArg.getDataAt(0)); - } - - private static final class AllowUnderscoreConverter extends CastNode { - - @Child private CastLogicalNode castLogical = CastLogicalNodeGen.create(false, false, false); - @Child private CastToVectorNode castVector = CastToVectorNodeGen.create(false); - - @Override - public RAbstractLogicalVector execute(Object value) { - try { - // TODO Catching RError! - return (RAbstractLogicalVector) castLogical.execute(castVector.execute(value)); - } catch (RError x) { - throw invalidAllowValue(this); - } - } - } - - private static RError invalidAllowValue(RBaseNode invokingNode) throws RError { - throw RError.error(invokingNode, RError.Message.INVALID_VALUE, "allow_"); - } } 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 8a4065d95e6c666f53f372e324f74dc8066960e7..d456c795fae43a462f4491e68ecb9fb00c51137f 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 @@ -22,19 +22,20 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +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.builtins.RBehavior.PURE; 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.ConditionProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.RString; import com.oracle.truffle.r.runtime.data.RStringVector; 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; @RBuiltin(name = "make.unique", kind = INTERNAL, parameterNames = {"names", "sep"}, behavior = PURE) @@ -44,6 +45,13 @@ public abstract class MakeUnique extends RBuiltinNode { private final ConditionProfile duplicatesProfile = ConditionProfile.createBinaryProfile(); private final NACheck dummyCheck = NACheck.create(); // never triggered (used for vector update) + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("names").defaultError(RError.SHOW_CALLER, RError.Message.NOT_CHARACTER_VECTOR, "names").mustNotBeNull().mustBe(stringValue()); + casts.arg("sep").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_STRING, "sep").mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst(); + + } + @Specialization protected RAbstractStringVector makeUnique(RAbstractStringVector names, String sep) { if (namesProfile.profile(names.getLength() == 0 || names.getLength() == 1)) { @@ -91,28 +99,4 @@ public abstract class MakeUnique extends RBuiltinNode { return s1 + sep + index; } - @Specialization(guards = "sepIsString(sep)") - protected RAbstractStringVector makeUnique(RAbstractStringVector names, RAbstractVector sep) { - return makeUnique(names, (String) sep.getDataAtAsObject(0)); - } - - @SuppressWarnings("unused") - @Specialization(guards = "!sepIsString(sep)") - protected RAbstractStringVector makeUniqueWrongSep(RAbstractStringVector names, RAbstractVector sep) { - throw RError.error(this, RError.Message.MUST_BE_STRING, "sep"); - } - - @SuppressWarnings("unused") - @Specialization(guards = "!namesIsStringVector(names)") - protected RAbstractStringVector makeUnique(RAbstractVector names, Object sep) { - throw RError.error(this, RError.Message.NOT_CHARACTER_VECTOR, "names"); - } - - protected boolean namesIsStringVector(RAbstractVector names) { - return names.getElementClass() == RString.class; - } - - protected boolean sepIsString(RAbstractVector sep) { - return sep.getElementClass() == RString.class && sep.getLength() == 1; - } } 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 d3deebf3f1f8eb22b6e59411c21b9c465da2bbbe..b7665cc04d28b7a03c4120e7ca7cc79ea2fe5f0f 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 @@ -23,9 +23,11 @@ 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.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; +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.frame.FrameSlot; @@ -35,9 +37,11 @@ import com.oracle.truffle.r.nodes.access.FrameSlotNode; 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.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.builtin.base.InfixFunctions.AccessArraySubscriptBuiltin; 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.runtime.AnonymousFrameVariable; @@ -45,13 +49,14 @@ 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.RAttributeProfiles; 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.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.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; @@ -63,9 +68,19 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @RBuiltin(name = "mapply", kind = INTERNAL, parameterNames = {"FUN", "dots", "MoreArgs"}, splitCaller = true, behavior = COMPLEX) public abstract class Mapply extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + // let's assume that mapply internal is never called directly, otherwise all hell ensues - + // even in GNU R .Internal(mapply(rep, 1:4, NULL)) causes a segfault + casts.arg("FUN").mustBe(instanceOf(RFunction.class)); + casts.arg("dots").mustBe(instanceOf(RAbstractListVector.class)); + // if we could map to an empty list, we could get rid of an additional specialization + casts.arg("MoreArgs").allowNull().mustBe(instanceOf(RAbstractListVector.class)); + } + protected static final class ElementNode extends Node { @Child private Length lengthNode; - @Child private AccessArraySubscriptBuiltin indexedLoadNode; + @Child private Subscript indexedLoadNode; @Child private WriteVariableNode writeVectorElementNode; private final String vectorElementName; private final String argName; @@ -74,7 +89,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(null)); - this.indexedLoadNode = insert(InfixFunctionsFactory.AccessArraySubscriptBuiltinNodeGen.create(null)); + this.indexedLoadNode = insert(SubscriptNodeGen.create(null)); this.writeVectorElementNode = insert(WriteVariableNode.createAnonymous(this.vectorElementName, null, Mode.REGULAR)); this.argName = argName; } @@ -83,7 +98,7 @@ public abstract class Mapply extends RBuiltinNode { @Child private MapplyInternalNode mapply = MapplyInternalNodeGen.create(); @Specialization - protected Object mApply(VirtualFrame frame, RFunction fun, RList dots, RList moreArgs) { + protected Object mApply(VirtualFrame frame, RFunction fun, RAbstractListVector dots, RAbstractListVector moreArgs) { Object[] result = mapply.execute(frame, dots, fun, moreArgs); // set here else it gets overridden by the iterator evaluation return RDataFactory.createList(result); @@ -91,7 +106,7 @@ public abstract class Mapply extends RBuiltinNode { @SuppressWarnings("unused") @Specialization - protected Object mApply(VirtualFrame frame, RFunction fun, RList dots, RNull moreArgs) { + protected Object mApply(VirtualFrame frame, RFunction fun, RAbstractListVector dots, RNull moreArgs) { return mApply(frame, fun, dots, RDataFactory.createList()); } @@ -109,9 +124,11 @@ public abstract class Mapply extends RBuiltinNode { } } - public abstract Object[] execute(VirtualFrame frame, RList dots, RFunction function, RList additionalArguments); + private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + + public abstract Object[] execute(VirtualFrame frame, RAbstractListVector dots, RFunction function, RAbstractListVector additionalArguments); - private static Object getVecElement(VirtualFrame frame, RList dots, int i, int listIndex, int[] lengths, AccessArraySubscriptBuiltin indexedLoadNode) { + 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) { @@ -136,7 +153,7 @@ public abstract class Mapply extends RBuiltinNode { } else { indexArg = new RArgsValuesAndNames(new Object[]{adjIndex + 1}, I_INDEX); } - return indexedLoadNode.execute(frame, vec, indexArg, EXACT, DROP); + return indexedLoadNode.executeBuiltin(frame, vec, indexArg, EXACT, DROP); } @@ -144,9 +161,9 @@ public abstract class Mapply extends RBuiltinNode { @Specialization(limit = "5", guards = {"dots.getLength() == cachedDots.getLength()", "moreArgs.getLength() == cachedMoreArgs.getLength()", "sameNames(dots, cachedDots)", "sameNames(moreArgs, cachedMoreArgs)"}) - protected Object[] cachedMApply(VirtualFrame frame, RList dots, RFunction function, RList moreArgs, - @Cached("dots") RList cachedDots, - @Cached("moreArgs") RList cachedMoreArgs, + protected Object[] cachedMApply(VirtualFrame frame, RAbstractListVector dots, RFunction function, RAbstractListVector moreArgs, + @Cached("dots") RAbstractListVector cachedDots, + @Cached("moreArgs") RAbstractListVector cachedMoreArgs, @Cached("createElementNodeArray(cachedDots, cachedMoreArgs)") ElementNode[] cachedElementNodeArray, @Cached("createCallNode(cachedElementNodeArray)") RCallNode callNode) { int dotsLength = dots.getLength(); @@ -179,11 +196,11 @@ public abstract class Mapply extends RBuiltinNode { } @Specialization(contains = "cachedMApply") - protected Object[] mApply(VirtualFrame frame, RList dots, RFunction function, RList moreArgs, + protected Object[] mApply(VirtualFrame frame, RAbstractListVector dots, RFunction function, RAbstractListVector moreArgs, @SuppressWarnings("unused") @Cached("createArgsIdentifier()") Object argsIdentifier, @Cached("createFrameSlotNode(argsIdentifier)") FrameSlotNode slotNode, @Cached("create()") RLengthNode lengthNode, - @Cached("createIndexedLoadNode()") AccessArraySubscriptBuiltin indexedLoadNode, + @Cached("createIndexedLoadNode()") Subscript indexedLoadNode, @Cached("createExplicitCallNode(argsIdentifier)") RCallNode callNode) { int dotsLength = dots.getLength(); int moreArgsLength = moreArgs.getLength(); @@ -198,13 +215,13 @@ public abstract class Mapply extends RBuiltinNode { } Object[] values = new Object[dotsLength + moreArgsLength]; String[] names = new String[dotsLength + moreArgsLength]; - RStringVector dotsNames = dots.getNames(); + RStringVector dotsNames = dots.getNames(attrProfiles); if (dotsNames != null) { for (int listIndex = 0; listIndex < dotsLength; listIndex++) { names[listIndex] = dotsNames.getDataAt(listIndex).isEmpty() ? null : dotsNames.getDataAt(listIndex); } } - RStringVector moreArgsNames = moreArgs.getNames(); + RStringVector moreArgsNames = moreArgs.getNames(attrProfiles); for (int listIndex = dotsLength; listIndex < dotsLength + moreArgsLength; listIndex++) { values[listIndex] = moreArgs.getDataAt(listIndex - dotsLength); names[listIndex] = moreArgsNames == null ? null : (moreArgsNames.getDataAt(listIndex - dotsLength).isEmpty() ? null : moreArgsNames.getDataAt(listIndex - dotsLength)); @@ -227,11 +244,9 @@ public abstract class Mapply extends RBuiltinNode { /** * Creates the {@link RCallNode} for this target. - * - * TODO names and moreArgs - * */ protected RCallNode createCallNode(ElementNode[] elementNodeArray) { + CompilerAsserts.neverPartOfCompilation(); RSyntaxNode[] syntaxNodes = new RSyntaxNode[elementNodeArray.length]; String[] names = new String[elementNodeArray.length]; for (int i = 0; i < syntaxNodes.length; i++) { @@ -242,14 +257,14 @@ public abstract class Mapply extends RBuiltinNode { return RCallNode.createCall(Lapply.createCallSourceSection(), null, ArgumentsSignature.get(names), syntaxNodes); } - protected ElementNode[] createElementNodeArray(RList dots, RList moreArgs) { + protected ElementNode[] createElementNodeArray(RAbstractListVector dots, RAbstractListVector moreArgs) { int length = dots.getLength() + moreArgs.getLength(); ElementNode[] elementNodes = new ElementNode[length]; - RStringVector dotsNames = dots.getNames(); + RStringVector dotsNames = dots.getNames(attrProfiles); for (int i = 0; i < dots.getLength(); i++) { elementNodes[i] = insert(new ElementNode(VECTOR_ELEMENT_PREFIX + (i + 1), dotsNames == null ? null : (dotsNames.getDataAt(i).isEmpty() ? null : dotsNames.getDataAt(i)))); } - RStringVector moreArgsNames = moreArgs.getNames(); + RStringVector moreArgsNames = moreArgs.getNames(attrProfiles); for (int i = dots.getLength(); i < dots.getLength() + moreArgs.getLength(); i++) { elementNodes[i] = insert(new ElementNode(VECTOR_ELEMENT_PREFIX + (i + 1), moreArgsNames == null ? null : moreArgsNames.getDataAt(i - dots.getLength()).isEmpty() ? null : moreArgsNames.getDataAt(i - dots.getLength()))); @@ -269,19 +284,19 @@ public abstract class Mapply extends RBuiltinNode { return RCallNode.createExplicitCall(argsIdentifier); } - protected AccessArraySubscriptBuiltin createIndexedLoadNode() { - return InfixFunctionsFactory.AccessArraySubscriptBuiltinNodeGen.create(null); + protected Subscript createIndexedLoadNode() { + return SubscriptNodeGen.create(null); } - protected boolean sameNames(RList list, RList cachedList) { - if (list.getNames() == null && cachedList.getNames() == null) { + protected boolean sameNames(RAbstractListVector list, RAbstractListVector cachedList) { + if (list.getNames(attrProfiles) == null && cachedList.getNames(attrProfiles) == null) { return true; - } else if (list.getNames() == null || cachedList.getNames() == null) { + } else if (list.getNames(attrProfiles) == null || cachedList.getNames(attrProfiles) == null) { return false; } else { for (int i = 0; i < list.getLength(); i++) { - String name = list.getNames().getDataAt(i); - String cachedName = cachedList.getNames().getDataAt(i); + String name = list.getNames(attrProfiles).getDataAt(i); + String cachedName = cachedList.getNames(attrProfiles).getDataAt(i); if (name == cachedName) { continue; 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 a24242b07bc1142361a4162b9efc6dc6d2746814..589e4cf028ed66e5fbe43a67a1e0d081485426e4 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 @@ -27,6 +27,9 @@ 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.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; @@ -48,8 +51,6 @@ 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; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; @@ -133,13 +134,6 @@ public abstract class MatMult extends RBuiltinNode { private final BranchProfile incompleteProfile = BranchProfile.create(); @CompilationFinal private boolean seenLargeMatrix; - @Specialization(guards = "matmat(a, b)") - protected RDoubleVector matmatmult(RAbstractDoubleVector a, RAbstractDoubleVector b) { - int[] aDimensions = a.getDimensions(); - int[] bDimensions = b.getDimensions(); - return doubleMatrixMultiply(a, b, aDimensions[0], aDimensions[1], bDimensions[0], bDimensions[1]); - } - 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); } @@ -268,598 +262,404 @@ public abstract class MatMult extends RBuiltinNode { } } - @Specialization(guards = "vecvec(a, b)") - protected RDoubleVector vecvecmult(RAbstractDoubleVector a, RAbstractDoubleVector b) { - if (a.getLength() != b.getLength()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); - } - double result = 0.0; - na.enable(a); - na.enable(b); - for (int k = 0; k < a.getLength(); k++) { - double aValue = a.getDataAt(k); - double bValue = b.getDataAt(k); - if (na.check(aValue) || na.check(bValue)) { - return RDataFactory.createDoubleVector(new double[]{RRuntime.DOUBLE_NA}, false, new int[]{1, 1}); + @Specialization + protected RDoubleVector multiply(RAbstractDoubleVector a, RAbstractDoubleVector b, + @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile bIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile lengthEquals) { + if (aIsMatrix.profile(a.isMatrix())) { + if (bIsMatrix.profile(b.isMatrix())) { + int[] aDimensions = a.getDimensions(); + int[] bDimensions = b.getDimensions(); + return doubleMatrixMultiply(a, b, aDimensions[0], aDimensions[1], bDimensions[0], bDimensions[1]); + } else { + int aRows = a.getDimensions()[0]; + int aCols = a.getDimensions()[1]; + int bRows; + int bCols; + if (lengthEquals.profile(aCols == b.getLength())) { + bRows = b.getLength(); + bCols = 1; + } else { + bRows = 1; + bCols = b.getLength(); + } + return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols); } - result = add.applyDouble(result, mult.applyDouble(aValue, bValue)); - } - return RDataFactory.createDoubleVector(new double[]{result}, true, new int[]{1, 1}); - } - - @Specialization(guards = "matvec(a, b)") - protected RDoubleVector matvecmult(RAbstractDoubleVector a, RAbstractDoubleVector b) { - int aRows = a.getDimensions()[0]; - int aCols = a.getDimensions()[1]; - int bRows; - int bCols; - if (aCols == b.getLength()) { - bRows = b.getLength(); - bCols = 1; - } else { - bRows = 1; - bCols = b.getLength(); - } - return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols); - } - - @Specialization(guards = "vecmat(a, b)") - protected RDoubleVector vecmatmult(RAbstractDoubleVector a, RAbstractDoubleVector b) { - int bRows = b.getDimensions()[0]; - int bCols = b.getDimensions()[1]; - int aRows; - int aCols; - if (bRows == a.getLength()) { - aRows = 1; - aCols = a.getLength(); } else { - aRows = a.getLength(); - aCols = 1; - } - return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols); - } - - // complex-complex - - @Specialization(guards = "matmat(a, b)") - protected RComplexVector matmatmult(RAbstractComplexVector a, RAbstractComplexVector b) { - final int aCols = a.getDimensions()[1]; - final int bRows = b.getDimensions()[0]; - if (aCols != bRows) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); - } - final int aRows = a.getDimensions()[0]; - final int bCols = b.getDimensions()[1]; - double[] result = new double[(aRows * bCols) << 1]; - na.enable(a); - na.enable(b); - for (int row = 0; row < aRows; row++) { - for (int col = 0; col < bCols; col++) { - RComplex x = RDataFactory.createComplexZero(); - for (int k = 0; k < aCols; k++) { - x = add.applyComplex(x, mult.applyComplex(a.getDataAt(k * aRows + row), b.getDataAt(col * bRows + k))); - na.check(x); + if (bIsMatrix.profile(b.isMatrix())) { + int bRows = b.getDimensions()[0]; + int bCols = b.getDimensions()[1]; + int aRows; + int aCols; + if (lengthEquals.profile(bRows == a.getLength())) { + aRows = 1; + aCols = a.getLength(); + } else { + aRows = a.getLength(); + aCols = 1; + } + 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); } - final int index = 2 * (col * aRows + row); - result[index] = x.getRealPart(); - result[index + 1] = x.getImaginaryPart(); + double result = 0.0; + na.enable(a); + na.enable(b); + for (int k = 0; k < a.getLength(); k++) { + double aValue = a.getDataAt(k); + double bValue = b.getDataAt(k); + if (na.check(aValue) || na.check(bValue)) { + return RDataFactory.createDoubleVector(new double[]{RRuntime.DOUBLE_NA}, false, new int[]{1, 1}); + } + result = add.applyDouble(result, mult.applyDouble(aValue, bValue)); + } + return RDataFactory.createDoubleVector(new double[]{result}, true, new int[]{1, 1}); } } - return RDataFactory.createComplexVector(result, na.neverSeenNA(), new int[]{aRows, bCols}); } - @Specialization(guards = "vecvec(a, b)") - protected RComplexVector vecvecmult(RAbstractComplexVector a, RAbstractComplexVector b) { - if (a.getLength() != b.getLength()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); - } - RComplex result = RDataFactory.createComplexZero(); - na.enable(a); - na.enable(b); - for (int k = 0; k < a.getLength(); k++) { - result = add.applyComplex(result, mult.applyComplex(a.getDataAt(k), b.getDataAt(k))); - na.check(result); - } - return RDataFactory.createComplexVector(new double[]{result.getRealPart(), result.getImaginaryPart()}, na.neverSeenNA(), new int[]{1, 1}); - } + // complex-complex - @Specialization(guards = "matvec(a, b)") - protected RComplexVector matvecmult(RAbstractComplexVector a, RAbstractComplexVector b) { - final int aCols = a.getDimensions()[1]; - final int aRows = a.getDimensions()[0]; - if (aCols != 1 && aCols != b.getLength()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); - } - na.enable(a); - na.enable(b); - if (notOneColumn.profile(aCols != 1)) { - double[] result = new double[aRows << 1]; - for (int row = 0; row < aRows; row++) { - RComplex x = RDataFactory.createComplexZero(); - for (int k = 0; k < b.getLength(); k++) { - x = add.applyComplex(x, mult.applyComplex(a.getDataAt(k * aRows + row), b.getDataAt(k))); - na.check(x); + @Specialization + 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())) { + final int aCols = a.getDimensions()[1]; + final int bRows = b.getDimensions()[0]; + if (aCols != bRows) { + errorProfile.enter(); + throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); } - result[row << 1] = x.getRealPart(); - result[row << 1 + 1] = x.getImaginaryPart(); - } - return RDataFactory.createComplexVector(result, na.neverSeenNA(), new int[]{aRows, 1}); - } else { - double[] result = new double[aRows * b.getLength() << 1]; - for (int row = 0; row < aRows; row++) { - for (int k = 0; k < b.getLength(); k++) { - RComplex x = mult.applyComplex(a.getDataAt(row), b.getDataAt(k)); - na.check(x); - result[(k * aRows + row) << 1] = x.getRealPart(); - result[(k * aRows + row) << 1 + 1] = x.getRealPart(); + final int aRows = a.getDimensions()[0]; + final int bCols = b.getDimensions()[1]; + double[] result = new double[(aRows * bCols) << 1]; + na.enable(a); + na.enable(b); + for (int row = 0; row < aRows; row++) { + for (int col = 0; col < bCols; col++) { + RComplex x = RDataFactory.createComplexZero(); + for (int k = 0; k < aCols; k++) { + x = add.applyComplex(x, mult.applyComplex(a.getDataAt(k * aRows + row), b.getDataAt(col * bRows + k))); + na.check(x); + } + final int index = 2 * (col * aRows + row); + result[index] = x.getRealPart(); + result[index + 1] = x.getImaginaryPart(); + } } - } - return RDataFactory.createComplexVector(result, na.neverSeenNA(), new int[]{aRows, b.getLength()}); - } - } - - @Specialization(guards = "vecmat(a, b)") - protected RComplexVector vecmatmult(RAbstractComplexVector a, RAbstractComplexVector b) { - final int bRows = b.getDimensions()[0]; - final int bCols = b.getDimensions()[1]; - if (bRows != 1 && bRows != a.getLength()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); - } - na.enable(a); - na.enable(b); - if (notOneRow.profile(bRows != 1)) { - double[] result = new double[bCols << 1]; - for (int k = 0; k < bCols; k++) { - RComplex x = RDataFactory.createComplexZero(); - for (int row = 0; row < a.getLength(); row++) { - x = add.applyComplex(x, mult.applyComplex(a.getDataAt(row), b.getDataAt(k * a.getLength() + row))); - na.check(x); + return RDataFactory.createComplexVector(result, na.neverSeenNA(), new int[]{aRows, bCols}); + } else { + final int aCols = a.getDimensions()[1]; + final int aRows = a.getDimensions()[0]; + if (aCols != 1 && aCols != b.getLength()) { + errorProfile.enter(); + throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); + } + na.enable(a); + na.enable(b); + if (notOneColumn.profile(aCols != 1)) { + double[] result = new double[aRows << 1]; + for (int row = 0; row < aRows; row++) { + RComplex x = RDataFactory.createComplexZero(); + for (int k = 0; k < b.getLength(); k++) { + x = add.applyComplex(x, mult.applyComplex(a.getDataAt(k * aRows + row), b.getDataAt(k))); + na.check(x); + } + result[row << 1] = x.getRealPart(); + result[(row << 1) + 1] = x.getImaginaryPart(); + } + return RDataFactory.createComplexVector(result, na.neverSeenNA(), new int[]{aRows, 1}); + } else { + double[] result = new double[aRows * b.getLength() << 1]; + for (int row = 0; row < aRows; row++) { + for (int k = 0; k < b.getLength(); k++) { + RComplex x = mult.applyComplex(a.getDataAt(row), b.getDataAt(k)); + na.check(x); + result[(k * aRows + row) << 1] = x.getRealPart(); + result[((k * aRows + row) << 1) + 1] = x.getRealPart(); + } + } + return RDataFactory.createComplexVector(result, na.neverSeenNA(), new int[]{aRows, b.getLength()}); } - result[k << 1] = x.getRealPart(); - result[k << 1 + 1] = x.getImaginaryPart(); } - return RDataFactory.createComplexVector(result, na.neverSeenNA(), new int[]{1, bCols}); } else { - double[] result = new double[(bCols * a.getLength()) << 1]; - for (int row = 0; row < a.getLength(); row++) { - for (int k = 0; k < bCols; k++) { - RComplex x = mult.applyComplex(a.getDataAt(row), b.getDataAt(k)); - na.check(x); - result[(k * a.getLength() + row) << 1] = x.getRealPart(); - result[(k * a.getLength() + row) << 1 + 1] = x.getImaginaryPart(); + if (bIsMatrix.profile(b.isMatrix())) { + final int bRows = b.getDimensions()[0]; + final int bCols = b.getDimensions()[1]; + if (bRows != 1 && bRows != a.getLength()) { + errorProfile.enter(); + throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); } + na.enable(a); + na.enable(b); + if (notOneRow.profile(bRows != 1)) { + double[] result = new double[bCols << 1]; + for (int k = 0; k < bCols; k++) { + RComplex x = RDataFactory.createComplexZero(); + for (int row = 0; row < a.getLength(); row++) { + x = add.applyComplex(x, mult.applyComplex(a.getDataAt(row), b.getDataAt(k * a.getLength() + row))); + na.check(x); + } + result[k << 1] = x.getRealPart(); + result[(k << 1) + 1] = x.getImaginaryPart(); + } + return RDataFactory.createComplexVector(result, na.neverSeenNA(), new int[]{1, bCols}); + } else { + double[] result = new double[(bCols * a.getLength()) << 1]; + for (int row = 0; row < a.getLength(); row++) { + for (int k = 0; k < bCols; k++) { + RComplex x = mult.applyComplex(a.getDataAt(row), b.getDataAt(k)); + na.check(x); + result[(k * a.getLength() + row) << 1] = x.getRealPart(); + result[((k * a.getLength() + row) << 1) + 1] = x.getImaginaryPart(); + } + } + return RDataFactory.createComplexVector(result, na.neverSeenNA(), new int[]{a.getLength(), bCols}); + } + } else { + if (a.getLength() != b.getLength()) { + errorProfile.enter(); + throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); + } + RComplex result = RDataFactory.createComplexZero(); + na.enable(a); + na.enable(b); + for (int k = 0; k < a.getLength(); k++) { + result = add.applyComplex(result, mult.applyComplex(a.getDataAt(k), b.getDataAt(k))); + na.check(result); + } + return RDataFactory.createComplexVector(new double[]{result.getRealPart(), result.getImaginaryPart()}, na.neverSeenNA(), new int[]{1, 1}); } - return RDataFactory.createComplexVector(result, na.neverSeenNA(), new int[]{a.getLength(), bCols}); } } // int-int - @Specialization(guards = "matmat(a, b)") - protected RIntVector matmatmult(RAbstractIntVector a, RAbstractIntVector b) { - final int aCols = a.getDimensions()[1]; - final int bRows = b.getDimensions()[0]; - if (aCols != bRows) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); - } - final int aRows = a.getDimensions()[0]; - final int bCols = b.getDimensions()[1]; - int[] result = new int[aRows * bCols]; - na.enable(a); - na.enable(b); - for (int row = 0; row < aRows; row++) { - for (int col = 0; col < bCols; col++) { - int x = 0; - for (int k = 0; k < aCols; k++) { - x = add.applyInteger(x, mult.applyInteger(a.getDataAt(k * aRows + row), b.getDataAt(col * bRows + k))); - na.check(x); + @Specialization + 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())) { + final int aCols = a.getDimensions()[1]; + final int bRows = b.getDimensions()[0]; + if (aCols != bRows) { + errorProfile.enter(); + throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); } - result[col * aRows + row] = x; - } - } - return RDataFactory.createIntVector(result, na.neverSeenNA(), new int[]{aRows, bCols}); - } - - @Specialization(guards = "vecvec(a, b)") - protected RIntVector vecvecmult(RAbstractIntVector a, RAbstractIntVector b) { - if (a.getLength() != b.getLength()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); - } - int result = 0; - na.enable(result); - for (int k = 0; k < a.getLength(); k++) { - result = add.applyInteger(result, mult.applyInteger(a.getDataAt(k), b.getDataAt(k))); - na.check(result); - } - return RDataFactory.createIntVector(new int[]{result}, na.neverSeenNA(), new int[]{1, 1}); - } - - @Specialization(guards = "matvec(a, b)") - protected RIntVector matvecmult(RAbstractIntVector a, RAbstractIntVector b) { - final int aCols = a.getDimensions()[1]; - final int aRows = a.getDimensions()[0]; - if (aCols != 1 && aCols != b.getLength()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); - } - na.enable(a); - na.enable(b); - if (notOneColumn.profile(aCols != 1)) { - int[] result = new int[aRows]; - for (int row = 0; row < aRows; row++) { - int x = 0; - for (int k = 0; k < b.getLength(); k++) { - x = add.applyInteger(x, mult.applyInteger(a.getDataAt(k * aRows + row), b.getDataAt(k))); - na.check(x); + final int aRows = a.getDimensions()[0]; + final int bCols = b.getDimensions()[1]; + int[] result = new int[aRows * bCols]; + na.enable(a); + na.enable(b); + for (int row = 0; row < aRows; row++) { + for (int col = 0; col < bCols; col++) { + int x = 0; + for (int k = 0; k < aCols; k++) { + x = add.applyInteger(x, mult.applyInteger(a.getDataAt(k * aRows + row), b.getDataAt(col * bRows + k))); + na.check(x); + } + result[col * aRows + row] = x; + } } - result[row] = x; - } - return RDataFactory.createIntVector(result, na.neverSeenNA(), new int[]{aRows, 1}); - } else { - int[] result = new int[aRows * b.getLength()]; - for (int row = 0; row < aRows; row++) { - for (int k = 0; k < b.getLength(); k++) { - int x = mult.applyInteger(a.getDataAt(row), b.getDataAt(k)); - na.check(x); - result[k * aRows + row] = x; + return RDataFactory.createIntVector(result, na.neverSeenNA(), new int[]{aRows, bCols}); + } else { + final int aCols = a.getDimensions()[1]; + final int aRows = a.getDimensions()[0]; + if (aCols != 1 && aCols != b.getLength()) { + errorProfile.enter(); + throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); } - } - return RDataFactory.createIntVector(result, na.neverSeenNA(), new int[]{aRows, b.getLength()}); - } - } - - @Specialization(guards = "vecmat(a, b)") - protected RIntVector vecmatmult(RAbstractIntVector a, RAbstractIntVector b) { - final int bCols = b.getDimensions()[1]; - final int bRows = b.getDimensions()[0]; - if (bRows != 1 && bRows != a.getLength()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); - } - na.enable(a); - na.enable(b); - if (notOneRow.profile(bRows != 1)) { - int[] result = new int[bCols]; - for (int k = 0; k < bCols; k++) { - int x = 0; - for (int row = 0; row < a.getLength(); row++) { - x = add.applyInteger(x, mult.applyInteger(a.getDataAt(row), b.getDataAt(k * a.getLength() + row))); - na.check(x); + na.enable(a); + na.enable(b); + if (notOneColumn.profile(aCols != 1)) { + int[] result = new int[aRows]; + for (int row = 0; row < aRows; row++) { + int x = 0; + for (int k = 0; k < b.getLength(); k++) { + x = add.applyInteger(x, mult.applyInteger(a.getDataAt(k * aRows + row), b.getDataAt(k))); + na.check(x); + } + result[row] = x; + } + return RDataFactory.createIntVector(result, na.neverSeenNA(), new int[]{aRows, 1}); + } else { + int[] result = new int[aRows * b.getLength()]; + for (int row = 0; row < aRows; row++) { + for (int k = 0; k < b.getLength(); k++) { + int x = mult.applyInteger(a.getDataAt(row), b.getDataAt(k)); + na.check(x); + result[k * aRows + row] = x; + } + } + return RDataFactory.createIntVector(result, na.neverSeenNA(), new int[]{aRows, b.getLength()}); } - result[k] = x; } - return RDataFactory.createIntVector(result, na.neverSeenNA(), new int[]{1, bCols}); } else { - int[] result = new int[bCols * a.getLength()]; - for (int row = 0; row < a.getLength(); row++) { - for (int k = 0; k < bCols; k++) { - int x = mult.applyInteger(a.getDataAt(row), b.getDataAt(k)); - na.check(x); - result[k * a.getLength() + row] = x; + if (bIsMatrix.profile(b.isMatrix())) { + final int bCols = b.getDimensions()[1]; + final int bRows = b.getDimensions()[0]; + if (bRows != 1 && bRows != a.getLength()) { + errorProfile.enter(); + throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); } + na.enable(a); + na.enable(b); + if (notOneRow.profile(bRows != 1)) { + int[] result = new int[bCols]; + for (int k = 0; k < bCols; k++) { + int x = 0; + for (int row = 0; row < a.getLength(); row++) { + x = add.applyInteger(x, mult.applyInteger(a.getDataAt(row), b.getDataAt(k * a.getLength() + row))); + na.check(x); + } + result[k] = x; + } + return RDataFactory.createIntVector(result, na.neverSeenNA(), new int[]{1, bCols}); + } else { + int[] result = new int[bCols * a.getLength()]; + for (int row = 0; row < a.getLength(); row++) { + for (int k = 0; k < bCols; k++) { + int x = mult.applyInteger(a.getDataAt(row), b.getDataAt(k)); + na.check(x); + result[k * a.getLength() + row] = x; + } + } + return RDataFactory.createIntVector(result, na.neverSeenNA(), new int[]{a.getLength(), bCols}); + } + } else { + if (a.getLength() != b.getLength()) { + errorProfile.enter(); + throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); + } + int result = 0; + na.enable(result); + for (int k = 0; k < a.getLength(); k++) { + result = add.applyInteger(result, mult.applyInteger(a.getDataAt(k), b.getDataAt(k))); + na.check(result); + } + return RDataFactory.createIntVector(new int[]{result}, na.neverSeenNA(), new int[]{1, 1}); } - return RDataFactory.createIntVector(result, na.neverSeenNA(), new int[]{a.getLength(), bCols}); } } // logical-logical - @Specialization(guards = "matmat(a, b)") - protected RIntVector matmatmult(RAbstractLogicalVector a, RAbstractLogicalVector b) { - return matmatmult(RClosures.createLogicalToIntVector(a), RClosures.createLogicalToIntVector(b)); - } - - @Specialization(guards = "vecvec(a, b)") - protected RIntVector vecvecmult(RAbstractLogicalVector a, RAbstractLogicalVector b) { - return vecvecmult(RClosures.createLogicalToIntVector(a), RClosures.createLogicalToIntVector(b)); - } - - @Specialization(guards = "matvec(a, b)") - protected RIntVector matvecmult(RAbstractLogicalVector a, RAbstractLogicalVector b) { - return matvecmult(RClosures.createLogicalToIntVector(a), RClosures.createLogicalToIntVector(b)); - } - - @Specialization(guards = "vecmat(a, b)") - protected RIntVector vecmatmult(RAbstractLogicalVector a, RAbstractLogicalVector b) { - return vecmatmult(RClosures.createLogicalToIntVector(a), RClosures.createLogicalToIntVector(b)); + @Specialization + protected RIntVector multiply(RAbstractLogicalVector aOriginal, RAbstractLogicalVector bOriginal, + @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { + return multiply(RClosures.createLogicalToIntVector(aOriginal), RClosures.createLogicalToIntVector(bOriginal), aIsMatrix, bIsMatrix); } // to int - @Specialization(guards = "matmat(a, b)") - protected RIntVector matmatmult(RAbstractLogicalVector a, RAbstractIntVector b) { - return matmatmult(RClosures.createLogicalToIntVector(a), b); - } - - @Specialization(guards = "vecvec(a, b)") - protected RIntVector vecvecmult(RAbstractLogicalVector a, RAbstractIntVector b) { - return vecvecmult(RClosures.createLogicalToIntVector(a), b); - } - - @Specialization(guards = "matvec(a, b)") - protected RIntVector matvecmult(RAbstractLogicalVector a, RAbstractIntVector b) { - return matvecmult(RClosures.createLogicalToIntVector(a), b); - } - - @Specialization(guards = "vecmat(a, b)") - protected RIntVector vecmatmult(RAbstractLogicalVector a, RAbstractIntVector b) { - return vecmatmult(RClosures.createLogicalToIntVector(a), b); - } - - @Specialization(guards = "matmat(a, b)") - protected RIntVector matmatmult(RAbstractIntVector a, RAbstractLogicalVector b) { - return matmatmult(a, RClosures.createLogicalToIntVector(b)); - } - - @Specialization(guards = "vecvec(a, b)") - protected RIntVector vecvecmult(RAbstractIntVector a, RAbstractLogicalVector b) { - return vecvecmult(a, RClosures.createLogicalToIntVector(b)); - } - - @Specialization(guards = "matvec(a, b)") - protected RIntVector matvecmult(RAbstractIntVector a, RAbstractLogicalVector b) { - return matvecmult(a, RClosures.createLogicalToIntVector(b)); + @Specialization + protected RIntVector multiply(RAbstractLogicalVector a, RAbstractIntVector b, + @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { + return multiply(RClosures.createLogicalToIntVector(a), b, aIsMatrix, bIsMatrix); } - @Specialization(guards = "vecmat(a, b)") - protected RIntVector vecmatmult(RAbstractIntVector a, RAbstractLogicalVector b) { - return vecmatmult(a, RClosures.createLogicalToIntVector(b)); + @Specialization + protected RIntVector multiply(RAbstractIntVector a, RAbstractLogicalVector b, + @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { + return multiply(a, RClosures.createLogicalToIntVector(b), aIsMatrix, bIsMatrix); } // to complex - @Specialization(guards = "matmat(a, b)") - protected RComplexVector matmatmult(RAbstractIntVector a, RAbstractComplexVector b) { - return matmatmult(RClosures.createIntToComplexVector(a), b); - } - - @Specialization(guards = "vecvec(a, b)") - protected RComplexVector vecvecmult(RAbstractIntVector a, RAbstractComplexVector b) { - return vecvecmult(RClosures.createIntToComplexVector(a), b); - } - - @Specialization(guards = "matvec(a, b)") - protected RComplexVector matvecmult(RAbstractIntVector a, RAbstractComplexVector b) { - return matvecmult(RClosures.createIntToComplexVector(a), b); - } - - @Specialization(guards = "vecmat(a, b)") - protected RComplexVector vecmatmult(RAbstractIntVector a, RAbstractComplexVector b) { - return vecmatmult(RClosures.createIntToComplexVector(a), b); - } - - @Specialization(guards = "matmat(a, b)") - protected RComplexVector matmatmult(RAbstractComplexVector a, RAbstractIntVector b) { - return matmatmult(a, RClosures.createIntToComplexVector(b)); - } - - @Specialization(guards = "vecvec(a, b)") - protected RComplexVector vecvecmult(RAbstractComplexVector a, RAbstractIntVector b) { - return vecvecmult(a, RClosures.createIntToComplexVector(b)); - } - - @Specialization(guards = "matvec(a, b)") - protected RComplexVector matvecmult(RAbstractComplexVector a, RAbstractIntVector b) { - return matvecmult(a, RClosures.createIntToComplexVector(b)); - } - - @Specialization(guards = "vecmat(a, b)") - protected RComplexVector vecmatmult(RAbstractComplexVector a, RAbstractIntVector b) { - return vecmatmult(a, RClosures.createIntToComplexVector(b)); - } - - @Specialization(guards = "matmat(a, b)") - protected RComplexVector matmatmult(RAbstractLogicalVector a, RAbstractComplexVector b) { - return matmatmult(RClosures.createLogicalToComplexVector(a), b); - } - - @Specialization(guards = "vecvec(a, b)") - protected RComplexVector vecvecmult(RAbstractLogicalVector a, RAbstractComplexVector b) { - return vecvecmult(RClosures.createLogicalToComplexVector(a), b); - } - - @Specialization(guards = "matvec(a, b)") - protected RComplexVector matvecmult(RAbstractLogicalVector a, RAbstractComplexVector b) { - return matvecmult(RClosures.createLogicalToComplexVector(a), b); - } - - @Specialization(guards = "vecmat(a, b)") - protected RComplexVector vecmatmult(RAbstractLogicalVector a, RAbstractComplexVector b) { - return vecmatmult(RClosures.createLogicalToComplexVector(a), b); - } - - @Specialization(guards = "matmat(a, b)") - protected RComplexVector matmatmult(RAbstractComplexVector a, RAbstractLogicalVector b) { - return matmatmult(a, RClosures.createLogicalToComplexVector(b)); - } - - @Specialization(guards = "vecvec(a, b)") - protected RComplexVector vecvecmult(RAbstractComplexVector a, RAbstractLogicalVector b) { - return vecvecmult(a, RClosures.createLogicalToComplexVector(b)); - } - - @Specialization(guards = "matvec(a, b)") - protected RComplexVector matvecmult(RAbstractComplexVector a, RAbstractLogicalVector b) { - return matvecmult(a, RClosures.createLogicalToComplexVector(b)); - } - - @Specialization(guards = "vecmat(a, b)") - protected RComplexVector vecmatmult(RAbstractComplexVector a, RAbstractLogicalVector b) { - return vecmatmult(a, RClosures.createLogicalToComplexVector(b)); - } - - @Specialization(guards = "matmat(a, b)") - protected RComplexVector matmatmult(RAbstractDoubleVector a, RAbstractComplexVector b) { - return matmatmult(RClosures.createDoubleToComplexVector(a), b); - } - - @Specialization(guards = "vecvec(a, b)") - protected RComplexVector vecvecmult(RAbstractDoubleVector a, RAbstractComplexVector b) { - return vecvecmult(RClosures.createDoubleToComplexVector(a), b); - } - - @Specialization(guards = "matvec(a, b)") - protected RComplexVector matvecmult(RAbstractDoubleVector a, RAbstractComplexVector b) { - return matvecmult(RClosures.createDoubleToComplexVector(a), b); + @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(guards = "vecmat(a, b)") - protected RComplexVector vecmatmult(RAbstractDoubleVector a, RAbstractComplexVector b) { - return vecmatmult(RClosures.createDoubleToComplexVector(a), b); + @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(guards = "matmat(a, b)") - protected RComplexVector matmatmult(RAbstractComplexVector a, RAbstractDoubleVector b) { - return matmatmult(a, RClosures.createDoubleToComplexVector(b)); + @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(guards = "vecvec(a, b)") - protected RComplexVector vecvecmult(RAbstractComplexVector a, RAbstractDoubleVector b) { - return vecvecmult(a, RClosures.createDoubleToComplexVector(b)); + @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(guards = "matvec(a, b)") - protected RComplexVector matvecmult(RAbstractComplexVector a, RAbstractDoubleVector b) { - return matvecmult(a, RClosures.createDoubleToComplexVector(b)); + @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(guards = "vecmat(a, b)") - protected RComplexVector vecmatmult(RAbstractComplexVector a, RAbstractDoubleVector b) { - return vecmatmult(a, RClosures.createDoubleToComplexVector(b)); + @Specialization + protected RComplexVector multiply(RAbstractComplexVector a, RAbstractDoubleVector b, + @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { + return multiply(a, RClosures.createDoubleToComplexVector(b), aIsMatrix, bIsMatrix); } // to double - @Specialization(guards = "matmat(a, b)") - protected RDoubleVector matmatmult(RAbstractIntVector a, RAbstractDoubleVector b) { - return matmatmult(RClosures.createIntToDoubleVector(a), b); - } - - @Specialization(guards = "vecvec(a, b)") - protected RDoubleVector vecvecmult(RAbstractIntVector a, RAbstractDoubleVector b) { - return vecvecmult(RClosures.createIntToDoubleVector(a), b); - } - - @Specialization(guards = "matvec(a, b)") - protected RDoubleVector matvecmult(RAbstractIntVector a, RAbstractDoubleVector b) { - return matvecmult(RClosures.createIntToDoubleVector(a), b); - } - - @Specialization(guards = "vecmat(a, b)") - protected RDoubleVector vecmatmult(RAbstractIntVector a, RAbstractDoubleVector b) { - return vecmatmult(RClosures.createIntToDoubleVector(a), b); - } - - @Specialization(guards = "matmat(a, b)") - protected RDoubleVector matmatmult(RAbstractDoubleVector a, RAbstractIntVector b) { - return matmatmult(a, RClosures.createIntToDoubleVector(b)); - } - - @Specialization(guards = "vecvec(a, b)") - protected RDoubleVector vecvecmult(RAbstractDoubleVector a, RAbstractIntVector b) { - return vecvecmult(a, RClosures.createIntToDoubleVector(b)); - } - - @Specialization(guards = "matvec(a, b)") - protected RDoubleVector matvecmult(RAbstractDoubleVector a, RAbstractIntVector b) { - return matvecmult(a, RClosures.createIntToDoubleVector(b)); - } - - @Specialization(guards = "vecmat(a, b)") - protected RDoubleVector vecmatmult(RAbstractDoubleVector a, RAbstractIntVector b) { - return vecmatmult(a, RClosures.createIntToDoubleVector(b)); - } - - @Specialization(guards = "matmat(a, b)") - protected RDoubleVector matmatmult(RAbstractLogicalVector a, RAbstractDoubleVector b) { - return matmatmult(RClosures.createLogicalToDoubleVector(a), b); - } - - @Specialization(guards = "vecvec(a, b)") - protected RDoubleVector vecvecmult(RAbstractLogicalVector a, RAbstractDoubleVector b) { - return vecvecmult(RClosures.createLogicalToDoubleVector(a), b); - } - - @Specialization(guards = "matvec(a, b)") - protected RDoubleVector matvecmult(RAbstractLogicalVector a, RAbstractDoubleVector b) { - return matvecmult(RClosures.createLogicalToDoubleVector(a), b); - } - - @Specialization(guards = "vecmat(a, b)") - protected RDoubleVector vecmatmult(RAbstractLogicalVector a, RAbstractDoubleVector b) { - return vecmatmult(RClosures.createLogicalToDoubleVector(a), b); - } - - @Specialization(guards = "matmat(a, b)") - protected RDoubleVector matmatmult(RAbstractDoubleVector a, RAbstractLogicalVector b) { - return matmatmult(a, RClosures.createLogicalToDoubleVector(b)); - } - - @Specialization(guards = "vecvec(a, b)") - protected RDoubleVector vecvecmult(RAbstractDoubleVector a, RAbstractLogicalVector b) { - return vecvecmult(a, RClosures.createLogicalToDoubleVector(b)); - } - - @Specialization(guards = "matvec(a, b)") - protected RDoubleVector matvecmult(RAbstractDoubleVector a, RAbstractLogicalVector b) { - return matvecmult(a, RClosures.createLogicalToDoubleVector(b)); - } - - @Specialization(guards = "vecmat(a, b)") - protected RDoubleVector vecmatmult(RAbstractDoubleVector a, RAbstractLogicalVector b) { - return vecmatmult(a, RClosures.createLogicalToDoubleVector(b)); - } - - // errors - - @SuppressWarnings("unused") @Specialization - protected RDoubleVector doRaw(RAbstractRawVector a, Object b) { - throw RError.error(this, RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR); + protected RDoubleVector multiply(RAbstractIntVector a, RAbstractDoubleVector b, + @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile bIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile lengthEquals) { + return multiply(RClosures.createIntToDoubleVector(a), b, aIsMatrix, bIsMatrix, lengthEquals); } - @SuppressWarnings("unused") @Specialization - protected RDoubleVector doRaw(Object a, RAbstractRawVector b) { - throw RError.error(this, RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR); + protected RDoubleVector multiply(RAbstractDoubleVector a, RAbstractIntVector b, + @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile bIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile lengthEquals) { + return multiply(a, RClosures.createIntToDoubleVector(b), aIsMatrix, bIsMatrix, lengthEquals); } - @SuppressWarnings("unused") @Specialization - protected RDoubleVector doString(RAbstractStringVector a, Object b) { - throw RError.error(this, RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR); + protected RDoubleVector multiply(RAbstractLogicalVector a, RAbstractDoubleVector b, + @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile bIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile lengthEquals) { + return multiply(RClosures.createLogicalToDoubleVector(a), b, aIsMatrix, bIsMatrix, lengthEquals); } - @SuppressWarnings("unused") @Specialization - protected RDoubleVector doString(Object a, RAbstractStringVector b) { - throw RError.error(this, RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR); + protected RDoubleVector multiply(RAbstractDoubleVector a, RAbstractLogicalVector b, + @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile bIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile lengthEquals) { + return multiply(a, RClosures.createLogicalToDoubleVector(b), aIsMatrix, bIsMatrix, lengthEquals); } - // guards - - protected static boolean matmat(RAbstractVector a, RAbstractVector b) { - return a.isMatrix() && b.isMatrix(); - } - - protected static boolean vecvec(RAbstractVector a, RAbstractVector b) { - return !a.isMatrix() && !b.isMatrix(); - } + // errors - protected static boolean matvec(RAbstractVector a, RAbstractVector b) { - return a.isMatrix() && !b.isMatrix(); + @Fallback + @TruffleBoundary + protected RDoubleVector doRaw(@SuppressWarnings("unused") Object a, @SuppressWarnings("unused") Object b) { + throw RError.error(this, RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR); } - protected static boolean vecmat(RAbstractVector a, RAbstractVector b) { - return !a.isMatrix() && b.isMatrix(); - } + // guards protected static boolean bothZeroDim(RAbstractVector a, RAbstractVector b) { return hasZeroDim(a) && hasZeroDim(b); 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 cf527e00fb408b7a65f378b1031ff47245ac7122..5bcf05eabfe6beed8bf00bbd2d764ba4f597a757 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,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +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; @@ -52,6 +53,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.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.ops.na.NACheck; @@ -74,13 +76,20 @@ public abstract class Match extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(2); + // TODO initially commented out because of use of scalars, the commented out version + // converted to new cast pipelines API + + // casts.arg("x").allowNull().mustBe(abstractVectorValue(), SHOW_CALLER, + // 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); } private RAbstractStringVector castString(RAbstractVector operand) { if (castString == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - castString = insert(CastStringNodeGen.create(false, false, false, false)); + castString = insert(CastStringNodeGen.create(false, false, false)); } return (RAbstractStringVector) castString.execute(operand); } @@ -97,21 +106,20 @@ public abstract class Match extends RBuiltinNode { @Specialization @SuppressWarnings("unused") - protected RIntVector match(RNull x, RNull table, RAbstractIntVector nomatchObj, Object incomparables) { + protected RIntVector match(RNull x, RNull table, int nomatch, Object incomparables) { return RDataFactory.createIntVector(0); } @Specialization @SuppressWarnings("unused") - protected RIntVector match(RNull x, RAbstractVector table, RAbstractIntVector nomatchObj, Object incomparables) { + protected RIntVector match(RNull x, RAbstractVector table, int nomatch, Object incomparables) { return RDataFactory.createIntVector(0); } @Specialization @SuppressWarnings("unused") - protected RIntVector match(RAbstractVector x, RNull table, RAbstractIntVector nomatchVec, Object incomparables) { + protected RIntVector match(RAbstractVector x, RNull table, int nomatch, Object incomparables) { int[] data = new int[x.getLength()]; - int nomatch = nomatchVec.getLength() == 0 ? RRuntime.INT_NA : nomatchVec.getDataAt(0); Arrays.fill(data, nomatch); naCheck.enable(nomatch); naCheck.check(nomatch); @@ -119,22 +127,22 @@ public abstract class Match extends RBuiltinNode { } @Specialization(guards = {"isFactor(x)", "isFactor(table)"}) - protected Object matchFactor(RAbstractIntVector x, RAbstractIntVector table, RAbstractIntVector nomatchObj, Object incomparables) { + protected Object matchFactor(RAbstractIntVector x, RAbstractIntVector table, int nomatch, Object incomparables) { naCheck.enable(x); naCheck.enable(table); - return matchRecursive(RClosures.createFactorToVector(x, true, attrProfiles), RClosures.createFactorToVector(table, true, attrProfiles), nomatchObj, incomparables); + return matchRecursive(RClosures.createFactorToVector(x, true, attrProfiles), RClosures.createFactorToVector(table, true, attrProfiles), nomatch, incomparables); } @Specialization(guards = {"isFactor(x)", "!isFactor(table)"}) - protected Object matchFactor(RAbstractIntVector x, RAbstractVector table, RAbstractIntVector nomatchObj, Object incomparables) { + protected Object matchFactor(RAbstractIntVector x, RAbstractVector table, int nomatch, Object incomparables) { naCheck.enable(x); - return matchRecursive(RClosures.createFactorToVector(x, true, attrProfiles), table, nomatchObj, incomparables); + return matchRecursive(RClosures.createFactorToVector(x, true, attrProfiles), table, nomatch, incomparables); } @Specialization(guards = {"!isFactor(x)", "isFactor(table)"}) - protected Object matchFactor(RAbstractVector x, RAbstractIntVector table, RAbstractIntVector nomatchObj, Object incomparables) { + protected Object matchFactor(RAbstractVector x, RAbstractIntVector table, int nomatch, Object incomparables) { naCheck.enable(table); - return matchRecursive(x, RClosures.createFactorToVector(table, true, attrProfiles), nomatchObj, incomparables); + return matchRecursive(x, RClosures.createFactorToVector(table, true, attrProfiles), nomatch, incomparables); } @Specialization @@ -144,8 +152,7 @@ public abstract class Match extends RBuiltinNode { } @Specialization - protected RIntVector match(RAbstractIntVector x, RAbstractIntVector table, RAbstractIntVector nomatchVec, @SuppressWarnings("unused") Object incomparables) { - int nomatch = nomatchVec.getLength() == 0 ? RRuntime.INT_NA : nomatchVec.getDataAt(0); + protected RIntVector match(RAbstractIntVector x, RAbstractIntVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) { int[] result = initResult(x.getLength(), nomatch); boolean matchAll = true; NonRecursiveHashMapInt hashTable; @@ -180,8 +187,7 @@ public abstract class Match extends RBuiltinNode { } @Specialization - protected RIntVector match(RAbstractDoubleVector x, RAbstractIntVector table, RAbstractIntVector nomatchVec, @SuppressWarnings("unused") Object incomparables) { - int nomatch = nomatchVec.getLength() == 0 ? RRuntime.INT_NA : nomatchVec.getDataAt(0); + protected RIntVector match(RAbstractDoubleVector x, RAbstractIntVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) { int[] result = initResult(x.getLength(), nomatch); boolean matchAll = true; NonRecursiveHashMapDouble hashTable; @@ -216,8 +222,7 @@ public abstract class Match extends RBuiltinNode { } @Specialization - protected RIntVector match(RAbstractIntVector x, RAbstractDoubleVector table, RAbstractIntVector nomatchVec, @SuppressWarnings("unused") Object incomparables) { - int nomatch = nomatchVec.getLength() == 0 ? RRuntime.INT_NA : nomatchVec.getDataAt(0); + protected RIntVector match(RAbstractIntVector x, RAbstractDoubleVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) { int[] result = initResult(x.getLength(), nomatch); boolean matchAll = true; NonRecursiveHashMapInt hashTable; @@ -259,8 +264,7 @@ public abstract class Match extends RBuiltinNode { } @Specialization - protected RIntVector match(RAbstractDoubleVector x, RAbstractDoubleVector table, RAbstractIntVector nomatchVec, @SuppressWarnings("unused") Object incomparables) { - int nomatch = nomatchVec.getLength() == 0 ? RRuntime.INT_NA : nomatchVec.getDataAt(0); + protected RIntVector match(RAbstractDoubleVector x, RAbstractDoubleVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) { int[] result = initResult(x.getLength(), nomatch); boolean matchAll = true; NonRecursiveHashMapDouble hashTable; @@ -295,8 +299,7 @@ public abstract class Match extends RBuiltinNode { } @Specialization - protected RIntVector match(RAbstractIntVector x, RAbstractLogicalVector table, RAbstractIntVector nomatchVec, @SuppressWarnings("unused") Object incomparables) { - int nomatch = nomatchVec.getLength() == 0 ? RRuntime.INT_NA : nomatchVec.getDataAt(0); + 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}; @@ -327,7 +330,7 @@ public abstract class Match extends RBuiltinNode { } @Specialization(guards = "x.getLength() == 1") - protected int matchSizeOne(RAbstractStringVector x, RAbstractStringVector table, RAbstractIntVector nomatchVec, @SuppressWarnings("unused") Object incomparables, // + 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) { @@ -349,13 +352,11 @@ public abstract class Match extends RBuiltinNode { } } notFoundProfile.enter(); - return nomatchVec.getLength() == 0 ? RRuntime.INT_NA : nomatchVec.getDataAt(0); - + return nomatch; } @Specialization - protected RIntVector match(RAbstractStringVector x, RAbstractStringVector table, RAbstractIntVector nomatchVec, @SuppressWarnings("unused") Object incomparables) { - int nomatch = nomatchVec.getLength() == 0 ? RRuntime.INT_NA : nomatchVec.getDataAt(0); + protected RIntVector match(RAbstractStringVector x, RAbstractStringVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) { int[] result = initResult(x.getLength(), nomatch); boolean matchAll = true; NonRecursiveHashMapCharacter hashTable; @@ -390,21 +391,27 @@ public abstract class Match extends RBuiltinNode { } @Specialization - protected RIntVector match(RAbstractLogicalVector x, RAbstractStringVector table, RAbstractIntVector nomatchObj, Object incomparables) { + 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(RAbstractRawVector x, RAbstractIntVector table, int nomatch, Object incomparables) { naCheck.enable(x); - return match(RClosures.createLogicalToStringVector(x), table, nomatchObj, incomparables); + return match(RClosures.createRawToStringVector(x), RClosures.createIntToStringVector(table), nomatch, incomparables); } @Specialization - protected RIntVector match(RAbstractIntVector x, RAbstractStringVector table, RAbstractIntVector nomatchObj, Object incomparables) { + protected RIntVector match(RAbstractIntVector x, RAbstractStringVector table, int nomatch, Object incomparables) { naCheck.enable(x); - return match(RClosures.createIntToStringVector(x), table, nomatchObj, incomparables); + return match(RClosures.createIntToStringVector(x), table, nomatch, incomparables); } @Specialization - protected RIntVector match(RAbstractDoubleVector x, RAbstractStringVector table, RAbstractIntVector nomatchObj, Object incomparables) { + protected RIntVector match(RAbstractDoubleVector x, RAbstractStringVector table, int nomatch, Object incomparables) { naCheck.enable(x); - return match(RClosures.createDoubleToStringVector(x), table, nomatchObj, incomparables); + return match(RClosures.createDoubleToStringVector(x), table, nomatch, incomparables); } @Specialization @@ -498,14 +505,14 @@ public abstract class Match extends RBuiltinNode { @Specialization @SuppressWarnings("unused") - protected RIntVector match(RFunction x, Object table, RAbstractIntVector nomatchObj, Object incomparables) { - throw RError.error(this, RError.Message.MATCH_VECTOR_ARGS); + 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, RAbstractIntVector nomatchObj, Object incomparables) { - throw RError.error(this, RError.Message.MATCH_VECTOR_ARGS); + protected RIntVector match(Object x, RFunction table, int nomatch, Object incomparables) { + throw RError.error(this, MATCH_VECTOR_ARGS); } protected boolean isStringVectorTable(RAbstractVector table) { 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 c857e315e262208120ed3bc35fcc060748174c39..a147ebce5d8d28ff9da96a6394e2b5b852ef2777 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 @@ -22,11 +22,11 @@ */ 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.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.SUBSTITUTE; 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; @@ -60,8 +60,6 @@ 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 { - @CompilationFinal private String lastFun; - @Override public Object[] getDefaultParameterValues() { return new Object[]{RMissing.instance, RRuntime.LOGICAL_TRUE}; @@ -69,7 +67,7 @@ public abstract class MatchFun extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.firstBoolean(1, "descend"); + casts.arg("descend").asLogicalVector().findFirst().map(toBoolean()); } @Specialization 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 0e5d9463a59853cfc98f67f2b6d0c00fb334644c..1df6d9c725b50fd3f3c8c5064423584fecd8a8e5 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 @@ -22,6 +22,8 @@ */ 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.toBoolean; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -31,27 +33,27 @@ import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.RList; -import com.oracle.truffle.r.runtime.data.RNull; 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; -@RBuiltin(name = "matrix", kind = INTERNAL, parameterNames = {"data", "nrow", "ncol", "isTrue(byrow)", "dimnames", "missingNrow", "missingNcol"}, behavior = PURE) +@RBuiltin(name = "matrix", kind = INTERNAL, parameterNames = {"data", "nrow", "ncol", "byrow", "dimnames", "missingNr", "missingNc"}, behavior = PURE) public abstract class Matrix extends RBuiltinNode { @Child private Transpose transpose; @Child private UpdateDimNames updateDimNames; + private final ConditionProfile byrowProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile isListProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile nrowMissingNcolGiven = ConditionProfile.createBinaryProfile(); private final ConditionProfile nrowGivenNcolMissing = ConditionProfile.createBinaryProfile(); private final ConditionProfile bothNrowNcolMissing = ConditionProfile.createBinaryProfile(); private final ConditionProfile empty = ConditionProfile.createBinaryProfile(); private final ConditionProfile isList = ConditionProfile.createBinaryProfile(); - public abstract RAbstractVector execute(RAbstractVector data, int nrow, int ncol, byte byrow, Object dimnames, byte missingNr, byte missingNc); + public abstract RAbstractVector execute(RAbstractVector data, int nrow, int ncol, boolean byrow, Object dimnames, boolean missingNr, boolean missingNc); private RAbstractVector updateDimNames(RAbstractVector vector, Object o) { if (updateDimNames == null) { @@ -63,108 +65,62 @@ public abstract class Matrix extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.firstIntegerWithError(1, RError.Message.NON_NUMERIC_MATRIX_EXTENT, null); // nrow - casts.firstIntegerWithError(2, RError.Message.NON_NUMERIC_MATRIX_EXTENT, null); // ncol - casts.toLogical(3); // byrow + casts.arg("data").asVector().mustBe(instanceOf(RAbstractVector.class)); + casts.arg("nrow").asIntegerVector().findFirst(RError.Message.NON_NUMERIC_MATRIX_EXTENT); + casts.arg("ncol").asIntegerVector().findFirst(RError.Message.NON_NUMERIC_MATRIX_EXTENT); + casts.arg("byrow").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("dimnames").allowNull().mustBe(instanceOf(RAbstractListVector.class)); + casts.arg("missingNr").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("missingNc").asLogicalVector().findFirst().map(toBoolean()); } - @Specialization(guards = "!isTrue(byrow)") - @SuppressWarnings("unused") - protected RAbstractVector matrixbc(RAbstractVector data, int nrow, int ncol, byte byrow, RNull dimnames, byte missingNr, byte missingNc) { - int[] dim = computeDimByCol(data.getLength(), nrow, ncol, missingNr, missingNc); - if (empty.profile(data.getLength() == 0)) { - if (isList.profile(data instanceof RList)) { - // matrix of NULL-s - return data.copyResizedWithDimensions(dim, true); - } else { - RVector res = data.createEmptySameType(0, RDataFactory.COMPLETE_VECTOR); - res.setDimensions(dim); - return res; - } + @Specialization + protected RAbstractVector matrix(RAbstractVector data, int nrow, int ncol, boolean byrow, Object dimnames, boolean missingNr, boolean missingNc) { + int[] dim; + if (byrowProfile.profile(byrow)) { + dim = computeDimByRow(data.getLength(), nrow, ncol, missingNr, missingNc); } else { - return data.copyResizedWithDimensions(dim, false); + dim = computeDimByCol(data.getLength(), nrow, ncol, missingNr, missingNc); } - } - - @Specialization(guards = "!isTrue(byrow)") - @SuppressWarnings("unused") - protected RAbstractVector matrixbc(RAbstractVector data, int nrow, int ncol, byte byrow, RList dimnames, byte missingNr, byte missingNc) { - int[] dim = computeDimByCol(data.getLength(), nrow, ncol, missingNr, missingNc); RAbstractVector res; if (empty.profile(data.getLength() == 0)) { - if (isList.profile(data instanceof RList)) { + if (isList.profile(data instanceof RAbstractListVector)) { // matrix of NULL-s res = data.copyResizedWithDimensions(dim, true); - res = updateDimNames(res, dimnames); + if (byrowProfile.profile(byrow)) { + if (transpose == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + transpose = insert(TransposeNodeGen.create(null)); + } + res = (RVector<?>) transpose.execute(res); + } + if (isListProfile.profile(dimnames instanceof RAbstractListVector)) { + res = updateDimNames(res, dimnames); + } } else { res = data.createEmptySameType(0, RDataFactory.COMPLETE_VECTOR); res.setDimensions(dim); } } else { res = data.copyResizedWithDimensions(dim, false); - res = updateDimNames(res, dimnames); - } - return res; - } - - @Specialization(guards = "isTrue(byrow)") - @SuppressWarnings("unused") - protected RAbstractVector matrixbr(RAbstractVector data, int nrow, int ncol, byte byrow, RNull dimnames, byte missingNr, byte missingNc) { - int[] dim = computeDimByRow(data.getLength(), nrow, ncol, missingNr, missingNc); - if (transpose == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - transpose = insert(TransposeNodeGen.create(null)); - } - RAbstractVector res; - if (empty.profile(data.getLength() == 0)) { - if (isList.profile(data instanceof RList)) { - // matrix of NULL-s - res = data.copyResizedWithDimensions(dim, true); - } else { - res = data.createEmptySameType(0, RDataFactory.COMPLETE_VECTOR); - res.setDimensions(dim); + if (byrowProfile.profile(byrow)) { + if (transpose == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + transpose = insert(TransposeNodeGen.create(null)); + } + res = (RVector<?>) transpose.execute(res); } - } else { - res = data.copyResizedWithDimensions(dim, false); - } - return (RAbstractVector) transpose.execute(res); - } - - @Specialization(guards = "isTrue(byrow)") - @SuppressWarnings("unused") - protected RAbstractVector matrixbr(RAbstractVector data, int nrow, int ncol, byte byrow, RList dimnames, byte missingNr, byte missingNc) { - int[] dim = computeDimByRow(data.getLength(), nrow, ncol, missingNr, missingNc); - if (transpose == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - transpose = insert(TransposeNodeGen.create(null)); - } - RAbstractVector res; - if (empty.profile(data.getLength() == 0)) { - if (isList.profile(data instanceof RList)) { - // matrix of NULL-s - res = (RVector) transpose.execute(data.copyResizedWithDimensions(dim, true)); + if (isListProfile.profile(dimnames instanceof RAbstractListVector)) { res = updateDimNames(res, dimnames); - } else { - res = data.createEmptySameType(0, RDataFactory.COMPLETE_VECTOR); - res.setDimensions(dim); } - } else { - res = (RVector) transpose.execute(data.copyResizedWithDimensions(dim, false)); - res = updateDimNames(res, dimnames); } return res; } - // - // Auxiliary methods. - // - - private int[] computeDimByCol(int size, int nrow, int ncol, byte missingNr, byte missingNc) { - final boolean mnr = missingNr == RRuntime.LOGICAL_TRUE; - final boolean mnc = missingNc == RRuntime.LOGICAL_TRUE; - if (bothNrowNcolMissing.profile(mnr && mnc)) { + private int[] computeDimByCol(int size, int nrow, int ncol, boolean missingNr, boolean missingNc) { + if (bothNrowNcolMissing.profile(missingNr && missingNc)) { return new int[]{size, 1}; - } else if (nrowGivenNcolMissing.profile(!mnr && mnc)) { + } else if (nrowGivenNcolMissing.profile(!missingNr && missingNc)) { if (nrow == 0 && size > 0) { throw RError.error(this, RError.Message.NROW_ZERO); } @@ -173,7 +129,7 @@ public abstract class Matrix extends RBuiltinNode { } else { return new int[]{nrow, 1 + ((size - 1) / nrow)}; } - } else if (nrowMissingNcolGiven.profile(mnr && !mnc)) { + } else if (nrowMissingNcolGiven.profile(missingNr && !missingNc)) { if (ncol == 0 && size > 0) { throw RError.error(this, RError.Message.NCOL_ZERO); } @@ -188,12 +144,10 @@ public abstract class Matrix extends RBuiltinNode { } } - private int[] computeDimByRow(int size, int nrow, int ncol, byte missingNr, byte missingNc) { - final boolean mnr = missingNr == RRuntime.LOGICAL_TRUE; - final boolean mnc = missingNc == RRuntime.LOGICAL_TRUE; - if (bothNrowNcolMissing.profile(mnr && mnc)) { + private int[] computeDimByRow(int size, int nrow, int ncol, boolean missingNr, boolean missingNc) { + if (bothNrowNcolMissing.profile(missingNr && missingNc)) { return new int[]{1, size}; - } else if (nrowGivenNcolMissing.profile(!mnr && mnc)) { + } else if (nrowGivenNcolMissing.profile(!missingNr && missingNc)) { if (nrow == 0 && size > 0) { throw RError.error(this, RError.Message.NROW_ZERO); } @@ -203,7 +157,7 @@ public abstract class Matrix extends RBuiltinNode { return new int[]{1 + ((size - 1) / nrow), nrow}; } - } else if (nrowMissingNcolGiven.profile(mnr && !mnc)) { + } else if (nrowMissingNcolGiven.profile(missingNr && !missingNc)) { if (ncol == 0 && size > 0) { throw RError.error(this, RError.Message.NCOL_ZERO); } @@ -217,12 +171,4 @@ public abstract class Matrix extends RBuiltinNode { return new int[]{ncol, nrow}; } } - - // - // Guards. - // - - protected static boolean isTrue(byte byrow) { - return RRuntime.fromLogical(byrow); - } } 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 d6eeb7853e25c838c76cc6aa65bbce15db863bc9..dac7f3b6519043254b51eaf7301031457480b257 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 @@ -22,6 +22,7 @@ */ 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.RDispatch.SUMMARY_GROUP_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -49,7 +50,7 @@ public abstract class Max extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.firstBoolean(1); + casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); } @Override 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 b8b26c8d0f9fa8c7b49909c99894cce1cb30ab7a..c9d99c5e7c2671b6946f99f8e3511332b497a13b 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 @@ -12,10 +12,14 @@ 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.notEmpty; +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.Message.INVALID_LOGICAL; 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.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; @@ -28,13 +32,26 @@ 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; -@RBuiltin(name = "merge", kind = INTERNAL, parameterNames = {"xinds", "xinds", "all.x", "all.y"}, behavior = PURE) +/** + * 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 { @Override protected void createCasts(CastBuilder casts) { - casts.firstLogical(2); - casts.firstLogical(3); + addIntegerCast(casts, "xinds"); + addIntegerCast(casts, "yinds"); + addLogicalCast(casts, "all.x"); + addLogicalCast(casts, "all.y"); + } + + private static void addIntegerCast(CastBuilder casts, String name) { + casts.arg(name).mustBe(integerValue()).asIntegerVector().mustBe(notEmpty()); + } + + private static void addLogicalCast(CastBuilder casts, String name) { + casts.arg(name).defaultError(INVALID_LOGICAL, "all.x").mustBe(numericValue()).asLogicalVector().findFirst().notNA().map(toBoolean()); } private static void isortWithIndex(int[] x, int[] indx, int n) { @@ -62,8 +79,8 @@ public abstract class Merge extends RBuiltinNode { } } - @Specialization(guards = {"xIndsAbstract.getLength() > 0", "xIndsAbstract.getLength() > 0", "!isNA(allX)", "!isNA(allY)"}) - RList merge(RAbstractIntVector xIndsAbstract, RAbstractIntVector yIndsAbstract, byte allX, byte allY) { + @Specialization + RList merge(RAbstractIntVector xIndsAbstract, RAbstractIntVector yIndsAbstract, boolean allX, boolean allY) { RIntVector xInds = xIndsAbstract.materialize(); RIntVector yInds = yIndsAbstract.materialize(); @@ -139,7 +156,7 @@ public abstract class Merge extends RBuiltinNode { ans.updateDataAt(0, RDataFactory.createIntVector(ansXData, RDataFactory.COMPLETE_VECTOR), null); ans.updateDataAt(1, RDataFactory.createIntVector(ansYData, RDataFactory.COMPLETE_VECTOR), null); - if (allX == RRuntime.LOGICAL_TRUE) { + if (allX) { int[] xLoneData = new int[nxLone]; ans.updateDataAt(2, RDataFactory.createIntVector(xLoneData, RDataFactory.COMPLETE_VECTOR), null); for (int i = 0, ll = 0; i < nxLone; i++) { @@ -149,7 +166,7 @@ public abstract class Merge extends RBuiltinNode { ans.updateDataAt(2, RNull.instance, null); } - if (allY == RRuntime.LOGICAL_TRUE) { + if (allY) { int[] yLoneData = new int[nyLone]; ans.updateDataAt(3, RDataFactory.createIntVector(yLoneData, RDataFactory.COMPLETE_VECTOR), null); for (int i = 0, ll = 0; i < nyLone; i++) { @@ -188,23 +205,4 @@ public abstract class Merge extends RBuiltinNode { return ans; } - @Fallback - Object merge(Object xInds, Object yInds, byte allX, byte allY) { - if (!(xInds instanceof Integer || (xInds instanceof RAbstractIntVector && ((RAbstractIntVector) xInds).getLength() > 0))) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "xinds"); - } - if (!(yInds instanceof Integer || (yInds instanceof RAbstractIntVector && ((RAbstractIntVector) yInds).getLength() > 0))) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "yinds"); - } - if (RRuntime.isNA(allX)) { - throw RError.error(this, RError.Message.INVALID_LOGICAL, "all.x"); - } else { - assert RRuntime.isNA(allY); - throw RError.error(this, RError.Message.INVALID_LOGICAL, "all.y"); - } - } - - protected boolean isNA(byte v) { - return RRuntime.isNA(v); - } } 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 0762b506438c0c6fadfb2a8b5ff8df88533c95de..b29a667281d58fef36227aa7ca87672db093c4af 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 @@ -22,6 +22,7 @@ */ 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.RDispatch.SUMMARY_GROUP_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -49,7 +50,7 @@ public abstract class Min extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.firstBoolean(1); + casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); } @Override 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 4bb9e38c5e451f4c803729a3eafbb5ef264c16c3..309dd7e602a088ada74d640fa8d4e48a1608fffe 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 @@ -186,7 +186,7 @@ public final class Missing extends RBuiltinNode { } @Override - public Object execute(VirtualFrame frame, Object... args) { + public Object executeBuiltin(VirtualFrame frame, Object... args) { throw RInternalError.shouldNotReachHere(); } 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 6f78bad2766e5866b55b01e2188e8cd499db806f..8278cc60981a9f8cf7b03093de861ca479e18696 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 @@ -24,6 +24,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.toBoolean; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -32,7 +33,6 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.LoopConditionProfile; import com.oracle.truffle.r.nodes.builtin.CastBuilder; -import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -49,7 +49,7 @@ public abstract class NChar extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.arg("x").mapIf(Predef.integerValue(), asIntegerVector(), asStringVector(true, false, false)); + 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()); 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 7ae86c1133e33980d7aaf413aa92d7bec032a94e..3756b5ba7cf1637a6a183d0d96331197eb16154c 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 @@ -23,7 +23,6 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte0; -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.runtime.builtins.RBehavior.COMPLEX; @@ -43,9 +42,9 @@ public abstract class NGetText extends RBuiltinNode { protected void createCasts(CastBuilder casts) { casts.arg("n").asIntegerVector().findFirst().mustBe(gte0()); - casts.arg("msg1").defaultError(RError.Message.MUST_BE_STRING, "msg1").mustBe(nullValue().not().and(stringValue())).asStringVector().mustBe(singleElement()).findFirst(); + casts.arg("msg1").defaultError(RError.Message.MUST_BE_STRING, "msg1").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst(); - casts.arg("msg2").defaultError(RError.Message.MUST_BE_STRING, "msg2").mustBe(nullValue().not().and(stringValue())).asStringVector().mustBe(singleElement()).findFirst(); + casts.arg("msg2").defaultError(RError.Message.MUST_BE_STRING, "msg2").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst(); } 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 1caab4877cdf457dc6a95aaa1290494718b26f32..c8c192044cd66d4cbdad17fe0fd83c12fcfe2ebf 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 @@ -22,32 +22,27 @@ */ 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.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.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.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.RNull; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -@RBuiltin(name = "nzchar", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) +@RBuiltin(name = "nzchar", kind = PRIMITIVE, parameterNames = {"x", "keepNA"}, behavior = PURE) public abstract class NZChar extends RBuiltinNode { - @Child private CastStringNode convertString; - private String coerceContent(Object content) { - if (convertString == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - convertString = insert(CastStringNodeGen.create(false, true, false, false)); - } - return (String) convertString.execute(content); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").allowNull().asStringVector(); + casts.arg("keepNA").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); } private static byte isNonZeroLength(String s) { @@ -55,42 +50,23 @@ public abstract class NZChar extends RBuiltinNode { } @Specialization - protected RLogicalVector rev(@SuppressWarnings("unused") RNull value) { + protected RLogicalVector rev(@SuppressWarnings("unused") RNull value, @SuppressWarnings("unused") boolean keepNA) { return RDataFactory.createEmptyLogicalVector(); } @Specialization - protected byte rev(int value) { - return isNonZeroLength(coerceContent(value)); - } - - @Specialization - protected byte rev(double value) { - return isNonZeroLength(coerceContent(value)); - } - - @Specialization - protected byte rev(byte value) { - return isNonZeroLength(coerceContent(value)); - } - - @Specialization - protected RLogicalVector rev(RStringVector vector) { - int len = vector.getLength(); - byte[] result = new byte[len]; - for (int i = 0; i < len; i++) { - result[i] = isNonZeroLength(vector.getDataAt(i)); - } - return RDataFactory.createLogicalVector(result, RDataFactory.COMPLETE_VECTOR); - } - - @Specialization - protected RLogicalVector rev(RAbstractVector vector) { + protected RLogicalVector rev(RAbstractStringVector vector, boolean keepNA) { int len = vector.getLength(); byte[] result = new byte[len]; + boolean hasNA = false; for (int i = 0; i < len; i++) { - result[i] = isNonZeroLength(coerceContent(vector.getDataAtAsObject(i))); + if (keepNA && RRuntime.isNA(vector.getDataAt(i))) { + result[i] = RRuntime.LOGICAL_NA; + hasNA = true; + } else { + result[i] = isNonZeroLength(vector.getDataAt(i)); + } } - return RDataFactory.createLogicalVector(result, RDataFactory.COMPLETE_VECTOR); + return RDataFactory.createLogicalVector(result, /* complete: */ keepNA && !hasNA); } } 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 7bac15ba3eaccd6e53b97eb63747a32f459cf338..d6947356d8bd852000e93c3c5397806839f48164 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 @@ -22,12 +22,15 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; import static com.oracle.truffle.r.runtime.builtins.RBehavior.MODIFIES_STATE; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; +import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; @@ -39,8 +42,19 @@ import com.oracle.truffle.r.runtime.env.REnvironment; public class NamespaceFunctions { + private static final class Casts { + private static void name(CastBuilder casts) { + casts.arg("name").mustBe(stringValue().or(instanceOf(RSymbol.class))); + } + } + @RBuiltin(name = "getRegisteredNamespace", kind = INTERNAL, parameterNames = {"name"}, behavior = READS_STATE) public abstract static class GetRegisteredNamespace extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.name(casts); + } + @Specialization protected Object doGetRegisteredNamespace(RAbstractStringVector name) { Object result = REnvironment.getRegisteredNamespace(name.getDataAt(0)); @@ -64,6 +78,11 @@ public class NamespaceFunctions { @RBuiltin(name = "isRegisteredNamespace", kind = INTERNAL, parameterNames = {"name"}, behavior = READS_STATE) public abstract static class IsRegisteredNamespace extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.name(casts); + } + @Specialization protected byte doIsRegisteredNamespace(RAbstractStringVector name) { Object result = REnvironment.getRegisteredNamespace(name.getDataAt(0)); @@ -92,8 +111,8 @@ public class NamespaceFunctions { return RRuntime.asLogical(env.isNamespaceEnv()); } - @Specialization - protected byte doIsNamespaceEnv(@SuppressWarnings("unused") RNull env) { + @Fallback + protected byte doIsNamespaceEnv(@SuppressWarnings("unused") Object env) { return RRuntime.LOGICAL_FALSE; } } @@ -108,17 +127,37 @@ public class NamespaceFunctions { @RBuiltin(name = "registerNamespace", kind = INTERNAL, parameterNames = {"name", "env"}, behavior = MODIFIES_STATE) public abstract static class RegisterNamespace extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.name(casts); + casts.arg("env").mustBe(instanceOf(REnvironment.class)); + } + @Specialization - protected RNull registerNamespace(String name, REnvironment env) { - if (REnvironment.registerNamespace(name, env) == null) { + protected RNull registerNamespace(RAbstractStringVector name, REnvironment env) { + if (REnvironment.registerNamespace(name.getDataAt(0), env) == null) { throw RError.error(this, RError.Message.NS_ALREADY_REG); } return RNull.instance; } + + @Specialization + protected RNull registerNamespace(RSymbol nameSym, REnvironment env) { + if (REnvironment.registerNamespace(nameSym.getName(), env) == null) { + throw RError.error(this, RError.Message.NS_ALREADY_REG); + } + return RNull.instance; + + } } @RBuiltin(name = "unregisterNamespace", kind = INTERNAL, parameterNames = {"name"}, behavior = MODIFIES_STATE) public abstract static class UnregisterNamespace extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.name(casts); + } + @Specialization protected RNull unregisterNamespace(RAbstractStringVector name) { doUnregisterNamespace(name.getDataAt(0)); 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 2d0e01271104e3abec2bbb8e8cddf2b318ab955a..52cbff0ce02ceead8e3e77bc4bb77cd657abcbd7 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 @@ -22,6 +22,11 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.eq; +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.Message.NOT_CHARACTER_VECTOR; +import static com.oracle.truffle.r.runtime.RError.Message.WRONG_WINSLASH; import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -33,6 +38,7 @@ import java.nio.file.NoSuchFileException; 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.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; @@ -48,6 +54,15 @@ public abstract class NormalizePath extends RBuiltinNode { private final ConditionProfile doesNotNeedToWork = ConditionProfile.createBinaryProfile(); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("path").mustBe(stringValue(), NOT_CHARACTER_VECTOR, "path"); + casts.arg("winslash").defaultError(NOT_CHARACTER_VECTOR, "winslash").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().mustBe(eq("/").or(eq("\\\\")).or(eq("\\")), + WRONG_WINSLASH); + // Note: NA is acceptable value for mustwork with special meaning + casts.arg("mustwork").asLogicalVector().findFirst(); + } + @Specialization @TruffleBoundary protected RStringVector doNormalizePath(RAbstractStringVector pathVec, @SuppressWarnings("unused") String winslash, byte mustWork) { @@ -85,9 +100,4 @@ public abstract class NormalizePath extends RBuiltinNode { return RDataFactory.createStringVector(results, RDataFactory.COMPLETE_VECTOR); } - @SuppressWarnings("unused") - @Specialization - protected Object doNormalizePath(Object path, Object winslash, Object mustWork) { - throw RError.error(this, RError.Message.WRONG_TYPE); - } } 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 9e3a9909e216cdc0abf4516cae1233641d6be7bb..b955f976259a0570876ef29af61ae0c96e28c07f 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 @@ -22,12 +22,14 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; import static com.oracle.truffle.r.runtime.RDispatch.COMPLEX_GROUP_GENERIC; 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 com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode; import com.oracle.truffle.r.runtime.RError; @@ -60,6 +62,11 @@ public class NumericalFunctions { super(RType.Integer, RError.Message.NON_NUMERIC_MATH, null); } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(numericValue().or(complexValue())); + } + @Override public RType calculateResultType(RType argumentType) { switch (argumentType) { @@ -98,6 +105,11 @@ public class NumericalFunctions { super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null); } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("z").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue())); + } + @Override public RType calculateResultType(RType argumentType) { switch (argumentType) { @@ -136,6 +148,11 @@ public class NumericalFunctions { super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null); } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("z").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue())); + } + @Override public RType calculateResultType(RType argumentType) { switch (argumentType) { @@ -174,6 +191,11 @@ public class NumericalFunctions { super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null); } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("z").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue())); + } + @Override public int op(byte op) { return op; @@ -202,6 +224,11 @@ public class NumericalFunctions { super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null); } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("z").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue())); + } + @Override public RType calculateResultType(RType argumentType) { switch (argumentType) { @@ -240,6 +267,11 @@ public class NumericalFunctions { super(RType.Logical); } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").defaultError(RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue()); + } + @Override public int op(byte op) { return op == RRuntime.LOGICAL_TRUE ? 1 : 0; @@ -264,6 +296,11 @@ public class NumericalFunctions { super(RType.Double, RError.Message.NON_NUMERIC_MATH, null); } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").defaultError(RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue().or(complexValue())); + } + @Override public int op(byte op) { return op; 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 0761d7875b918bc0585456735f27084b2550a78f..3eb6440923f772d5c4ba513b9dda0b2723d8a656 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 @@ -36,6 +36,7 @@ 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.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RError; @@ -65,6 +66,11 @@ public abstract class OnExit extends RBuiltinNode { private final BranchProfile invalidateProfile = BranchProfile.create(); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("add").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); + } + @Override public Object[] getDefaultParameterValues() { return new Object[]{RNull.instance, RRuntime.LOGICAL_FALSE}; 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 8749d957ebb229eca5851746c446f455812501af..f5487620db0fb63a21abd652f71710e0cf582d99 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM; import static com.oracle.truffle.r.runtime.builtins.RBehavior.MODIFIES_STATE; import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE; @@ -33,8 +34,11 @@ import java.util.Set; 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.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +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; @@ -60,6 +64,8 @@ public class OptionsFunctions { @RBuiltin(name = "options", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"..."}, behavior = MODIFIES_STATE) public abstract static class Options extends RBuiltinNode { + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); + private final ConditionProfile argNameNull = ConditionProfile.createBinaryProfile(); private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); @@ -83,81 +89,104 @@ public class OptionsFunctions { return options(RMissing.instance); } + private static final class InvisibleResult extends Throwable { + private static final long serialVersionUID = 5767688593421435507L; + + private final RList value; + + protected InvisibleResult(RList value) { + this.value = value; + } + } + @Specialization(guards = "!isMissing(args)") - @TruffleBoundary - protected Object options(RArgsValuesAndNames args) { + protected Object options(VirtualFrame frame, RArgsValuesAndNames args) { try { - ROptions.ContextStateImpl options = RContext.getInstance().stateROptions; - Object[] values = args.getArguments(); - ArgumentsSignature signature = args.getSignature(); - Object[] data = new Object[values.length]; - String[] names = new String[values.length]; - for (int i = 0; i < values.length; i++) { - String argName = signature.getName(i); - Object value = values[i]; - if (argNameNull.profile(argName == null)) { - // getting - String optionName = null; - if (value instanceof RStringVector) { - // ignore rest (cf GnuR) - optionName = ((RStringVector) value).getDataAt(0); - } else if (value instanceof String) { - optionName = (String) value; - } else if (value instanceof RList) { - // setting - RList list = (RList) value; - RStringVector thisListnames = null; - Object nn = list.getNames(attrProfiles); - if (nn instanceof RStringVector) { - thisListnames = (RStringVector) nn; - } else { - throw RInternalError.shouldNotReachHere(); - } - Object[] listData = new Object[list.getLength()]; - String[] listNames = new String[listData.length]; - for (int j = 0; j < listData.length; j++) { - String name = thisListnames.getDataAt(j); - Object previousVal = options.getValue(name); - listData[j] = previousVal == null ? RNull.instance : previousVal; - listNames[j] = name; - options.setValue(name, list.getDataAtAsObject(j)); - } - // if this is the only argument, no need to copy, can just return - if (values.length == 1) { - data = listData; - names = listNames; - break; - } else { - // resize and copy - int newSize = values.length - 1 + listData.length; - Object[] newData = new Object[newSize]; - String[] newNames = new String[newSize]; - System.arraycopy(data, 0, newData, 0, i); - System.arraycopy(names, 0, newNames, 0, i); - System.arraycopy(listData, 0, newData, i, listData.length); - System.arraycopy(listNames, 0, newNames, i, listNames.length); - data = newData; - names = newNames; - } + return optionsInternal(args); + } catch (OptionsException ex) { + throw RError.error(this, ex); + } catch (InvisibleResult ex) { + visibility.execute(frame, false); + return ex.value; + } + } + + @TruffleBoundary + private Object optionsInternal(RArgsValuesAndNames args) throws OptionsException, InvisibleResult { + boolean invisible = false; + ROptions.ContextStateImpl options = RContext.getInstance().stateROptions; + Object[] values = args.getArguments(); + ArgumentsSignature signature = args.getSignature(); + Object[] data = new Object[values.length]; + String[] names = new String[values.length]; + for (int i = 0; i < values.length; i++) { + String argName = signature.getName(i); + Object value = values[i]; + if (argNameNull.profile(argName == null)) { + // getting + String optionName = null; + if (value instanceof RStringVector) { + // ignore rest (cf GnuR) + optionName = ((RStringVector) value).getDataAt(0); + } else if (value instanceof String) { + optionName = (String) value; + } else if (value instanceof RList) { + // setting + RList list = (RList) value; + RStringVector thisListnames = null; + Object nn = list.getNames(attrProfiles); + if (nn instanceof RStringVector) { + thisListnames = (RStringVector) nn; + } else { + throw RInternalError.shouldNotReachHere(); + } + Object[] listData = new Object[list.getLength()]; + String[] listNames = new String[listData.length]; + for (int j = 0; j < listData.length; j++) { + String name = thisListnames.getDataAt(j); + Object previousVal = options.getValue(name); + listData[j] = previousVal == null ? RNull.instance : previousVal; + listNames[j] = name; + options.setValue(name, list.getDataAtAsObject(j)); + } + // if this is the only argument, no need to copy, can just return + if (values.length == 1) { + data = listData; + names = listNames; + break; } else { - throw RError.error(this, Message.INVALID_UNNAMED_ARGUMENT); + // resize and copy + int newSize = values.length - 1 + listData.length; + Object[] newData = new Object[newSize]; + String[] newNames = new String[newSize]; + System.arraycopy(data, 0, newData, 0, i); + System.arraycopy(names, 0, newNames, 0, i); + System.arraycopy(listData, 0, newData, i, listData.length); + System.arraycopy(listNames, 0, newNames, i, listNames.length); + data = newData; + names = newNames; } - Object optionVal = options.getValue(optionName); - data[i] = optionVal == null ? RNull.instance : optionVal; - names[i] = optionName; } else { - // setting - Object previousVal = options.getValue(argName); - data[i] = previousVal == null ? RNull.instance : previousVal; - names[i] = argName; - options.setValue(argName, value); - // any settings means result is invisible - RContext.getInstance().setVisible(false); + throw RError.error(this, Message.INVALID_UNNAMED_ARGUMENT); } + Object optionVal = options.getValue(optionName); + data[i] = optionVal == null ? RNull.instance : optionVal; + names[i] = optionName; + } else { + // setting + Object previousVal = options.getValue(argName); + data[i] = previousVal == null ? RNull.instance : previousVal; + names[i] = argName; + options.setValue(argName, value); + // any settings means result is invisible + invisible = true; } - return RDataFactory.createList(data, RDataFactory.createStringVector(names, RDataFactory.COMPLETE_VECTOR)); - } catch (OptionsException ex) { - throw RError.error(this, ex); + } + RList result = RDataFactory.createList(data, RDataFactory.createStringVector(names, RDataFactory.COMPLETE_VECTOR)); + if (invisible) { + throw new InvisibleResult(result); + } else { + return result; } } @@ -169,6 +198,11 @@ public class OptionsFunctions { @RBuiltin(name = "getOption", kind = INTERNAL, parameterNames = "x", behavior = READS_STATE) public abstract static class GetOption extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_STRING, "x").mustBe(stringValue()).asStringVector().findFirst(); + } + @TruffleBoundary @Specialization protected Object getOption(RAbstractStringVector x) { 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 0e62a878031792191dbddc2c80506631455cd2c1..215877a5efae0fc49bd9bbc7c85754a24139557d 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 @@ -12,10 +12,15 @@ */ 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.toBoolean; +import static com.oracle.truffle.r.runtime.RError.Message.INVALID_LOGICAL; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import java.text.Collator; +import java.text.ParseException; +import java.text.RuleBasedCollator; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -31,6 +36,7 @@ import com.oracle.truffle.r.nodes.builtin.base.OrderNodeGen.OrderVector1NodeGen; import com.oracle.truffle.r.nodes.unary.CastToVectorNode; 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.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; @@ -51,8 +57,6 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; @RBuiltin(name = "order", kind = INTERNAL, parameterNames = {"na.last", "decreasing", "..."}, behavior = PURE) public abstract class Order extends RPrecedenceBuiltinNode { - public abstract RIntVector executeRIntVector(byte naLast, byte dec, RArgsValuesAndNames args); - @Child private OrderVector1Node orderVector1Node; @Child private CastToVectorNode castVector; @Child private CastToVectorNode castVector2; @@ -63,8 +67,13 @@ public abstract class Order extends RPrecedenceBuiltinNode { private static final int[] SINCS = {1073790977, 268460033, 67121153, 16783361, 4197377, 1050113, 262913, 65921, 16577, 4193, 1073, 281, 77, 23, 8, 1, 0}; private OrderVector1Node initOrderVector1() { - if (orderVector1Node == null) { - orderVector1Node = insert(OrderVector1NodeGen.create()); + return initOrderVector1(false); + } + + private OrderVector1Node initOrderVector1(boolean needsStringCollation) { + if (orderVector1Node == null || needsStringCollation && !orderVector1Node.needsStringCollation) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + orderVector1Node = insert(OrderVector1NodeGen.create(needsStringCollation)); } return orderVector1Node; } @@ -87,7 +96,8 @@ public abstract class Order extends RPrecedenceBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.firstBoolean(0, "na.last").firstBoolean(1, "decreasing"); + casts.arg("na.last").mustBe(numericValue(), INVALID_LOGICAL, "na.last").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("decreasing").mustBe(numericValue(), INVALID_LOGICAL, "decreasing").asLogicalVector().findFirst().map(toBoolean()); } private int cmp(Object v, int i, int j, boolean naLast) { @@ -109,6 +119,7 @@ public abstract class Order extends RPrecedenceBuiltinNode { Object[] vectors = args.getArguments(); RAbstractIntVector v = (RAbstractIntVector) castVector(vectors[0]); int n = v.getLength(); + reportWork(n); int[] indx = new int[n]; for (int i = 0; i < indx.length; i++) { @@ -128,6 +139,7 @@ public abstract class Order extends RPrecedenceBuiltinNode { Object[] vectors = args.getArguments(); RAbstractDoubleVector v = (RAbstractDoubleVector) castVector(vectors[0]); int n = v.getLength(); + reportWork(n); int[] indx = new int[n]; for (int i = 0; i < indx.length; i++) { @@ -150,17 +162,32 @@ public abstract class Order extends RPrecedenceBuiltinNode { } @Specialization(guards = {"oneVec(args)", "isFirstStringPrecedence(args)"}) - Object orderString(boolean naLast, boolean decreasing, RArgsValuesAndNames args) { + Object orderString(boolean naLast, boolean decreasing, RArgsValuesAndNames args, + @Cached("create()") BranchProfile collationProfile) { Object[] vectors = args.getArguments(); RAbstractStringVector v = (RAbstractStringVector) castVector(vectors[0]); int n = v.getLength(); + reportWork(n); + + boolean needsCollation = false; + outer: for (int i = 0; i < n; i++) { + String str = v.getDataAt(i); + for (int i2 = 0; i2 < str.length(); i2++) { + char c = str.charAt(i2); + if (c > 127) { + collationProfile.enter(); + needsCollation = true; + break outer; + } + } + } int[] indx = new int[n]; for (int i = 0; i < indx.length; i++) { indx[i] = i; } RIntVector indxVec = RDataFactory.createIntVector(indx, RDataFactory.COMPLETE_VECTOR); - initOrderVector1().execute(indxVec, v, naLast, decreasing, null); + initOrderVector1(needsCollation).execute(indxVec, v, naLast, decreasing, null); for (int i = 0; i < indx.length; i++) { indx[i] = indx[i] + 1; } @@ -173,6 +200,7 @@ public abstract class Order extends RPrecedenceBuiltinNode { Object[] vectors = args.getArguments(); RAbstractComplexVector v = (RAbstractComplexVector) castVector(vectors[0]); int n = v.getLength(); + reportWork(n); int[] indx = new int[n]; for (int i = 0; i < indx.length; i++) { @@ -210,6 +238,7 @@ public abstract class Order extends RPrecedenceBuiltinNode { Object[] vectors = args.getArguments(); RAbstractVector v = castVector(vectors[0]); int n = v.getLength(); + reportWork(n); vectors[0] = v; int length = lengthProfile.profile(vectors.length); for (int i = 1; i < length; i++) { @@ -285,6 +314,12 @@ public abstract class Order extends RPrecedenceBuiltinNode { abstract static class OrderVector1Node extends RBaseNode { private final ConditionProfile decProfile = ConditionProfile.createBinaryProfile(); + private final boolean needsStringCollation; + + protected OrderVector1Node(boolean needsStringCollation) { + this.needsStringCollation = needsStringCollation; + } + public abstract Object execute(Object v, Object dv, boolean naLast, boolean dec, Object rho); @Specialization @@ -518,7 +553,7 @@ public abstract class Order extends RPrecedenceBuiltinNode { while (j >= lo + h) { int a = indx[j - h]; int b = itmp; - int c = compare(collator, dv.getDataAt(a), dv.getDataAt(b)); + int c = compareString(collator, dv.getDataAt(a), dv.getDataAt(b)); if (decProfile.profile(dec)) { if (!(c < 0 || (c == 0 && a > b))) { break; @@ -536,14 +571,32 @@ public abstract class Order extends RPrecedenceBuiltinNode { } } + private int compareString(Collator collator, String dataAt, String dataAt2) { + if (needsStringCollation) { + return compare(collator, dataAt, dataAt2); + } else { + return dataAt.compareToIgnoreCase(dataAt2); + } + } + @TruffleBoundary private static int compare(Collator collator, String dataAt, String dataAt2) { return collator.compare(dataAt, dataAt2); } @TruffleBoundary - private static Collator createCollator() { - return Collator.getInstance(); + private Collator createCollator() { + if (!needsStringCollation) { + return null; + } + // add rule for space before '_' + Collator collator = Collator.getInstance(); + String rules = ((RuleBasedCollator) collator).getRules(); + try { + return new RuleBasedCollator(rules.replaceAll("<'\u005f'", "<' '<'\u005f'")); + } catch (ParseException e) { + throw RInternalError.shouldNotReachHere(e); + } } private static boolean lt(RComplex a, RComplex b) { 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 3bc987dd1af7768ab0d8bcaa9915e4efc7d7d21c..4f841fb44d50e02358d9a6f652bc4736735e83ee 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,6 +22,9 @@ */ 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; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -42,14 +45,16 @@ public abstract class PMatch extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(2).toLogical(3); + casts.arg("x").asStringVector(); + casts.arg("table").asStringVector(); + casts.arg("nomatch").mapNull(constant(RRuntime.INT_NA)).asIntegerVector(); + casts.arg("duplicates.ok").mustBe(numericValue()).asLogicalVector().findFirst().map(toBoolean()); } @Specialization - protected RIntVector doPMatch(RAbstractStringVector x, RAbstractStringVector table, int nomatch, byte duplicatesOk) { + protected RIntVector doPMatch(RAbstractStringVector x, RAbstractStringVector table, int nomatch, boolean duplicatesOk) { int xl = x.getLength(); int tl = table.getLength(); - boolean dupsOk = RRuntime.fromLogical(duplicatesOk); int[] matches = new int[xl]; boolean[] matched = new boolean[xl]; boolean[] used = new boolean[tl]; @@ -77,7 +82,7 @@ public abstract class PMatch extends RBuiltinNode { if (match) { matches[i] = t + 1; matched[i] = true; - if (!dupsOk) { + if (!duplicatesOk) { used[t] = true; } } 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 a64a2900dbbed90e93852da8d52b9ade8aaee138..093844fbf9789bc5fcea96defe3299c221003279 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 @@ -22,13 +22,20 @@ */ 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; 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.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.PMinMaxNodeGen.MultiElemStringHandlerNodeGen; import com.oracle.truffle.r.nodes.unary.CastDoubleNode; @@ -45,9 +52,9 @@ import com.oracle.truffle.r.nodes.unary.PrecedenceNodeGen; import com.oracle.truffle.r.nodes.unary.UnaryArithmeticReduceNode.ReduceSemantics; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -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; @@ -83,7 +90,12 @@ public abstract class PMinMax extends RBuiltinNode { this.op = factory.create(); } - private byte handleString(Object[] argValues, byte naRm, int offset, int ind, int maxLength, byte warning, Object data) { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("na.rm").defaultError(SHOW_CALLER, Message.INVALID_VALUE, "na.rm").mustBe(numericValue()).asLogicalVector().findFirst().mustBe(logicalNA().not()).map(toBoolean()); + } + + private byte handleString(Object[] argValues, boolean naRm, int offset, int ind, int maxLength, byte warning, Object data) { if (stringHandler == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); stringHandler = insert(MultiElemStringHandlerNodeGen.create(semantics, factory, na)); @@ -118,7 +130,7 @@ public abstract class PMinMax extends RBuiltinNode { private CastNode getStringCastNode() { if (castString == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - castString = insert(CastStringNodeGen.create(true, true, true, false)); + castString = insert(CastStringNodeGen.create(true, true, true)); } return castString; } @@ -141,22 +153,22 @@ public abstract class PMinMax extends RBuiltinNode { } @Specialization(guards = {"isIntegerPrecedence(args)", "args.getLength() == 0"}) - protected Object pMinMaxNoneVecInt(@SuppressWarnings("unused") byte naRm, @SuppressWarnings("unused") RArgsValuesAndNames args) { + protected Object pMinMaxNoneVecInt(@SuppressWarnings("unused") boolean naRm, @SuppressWarnings("unused") RArgsValuesAndNames args) { return RDataFactory.createEmptyIntVector(); } @Specialization(guards = {"isIntegerPrecedence(args)", "args.getLength() == 1"}) - protected Object pMinMaxOneVecInt(@SuppressWarnings("unused") byte naRm, RArgsValuesAndNames args) { + protected Object pMinMaxOneVecInt(@SuppressWarnings("unused") boolean naRm, RArgsValuesAndNames args) { return args.getArgument(0); } @Specialization(guards = {"isIntegerPrecedence(args)", "args.getLength() > 1"}) - protected RIntVector pMinMaxInt(byte naRm, RArgsValuesAndNames args) { + protected RIntVector pMinMaxInt(boolean naRm, RArgsValuesAndNames args) { int maxLength = convertToVectorAndEnableNACheck(args, getIntegerCastNode()); if (lengthProfile.profile(maxLength == 0)) { return RDataFactory.createEmptyIntVector(); } else { - boolean profiledNaRm = naRmProfile.profile(naRm == RRuntime.LOGICAL_TRUE); + boolean profiledNaRm = naRmProfile.profile(naRm); int[] data = new int[maxLength]; Object[] argValues = args.getArguments(); boolean warningAdded = false; @@ -188,29 +200,29 @@ public abstract class PMinMax extends RBuiltinNode { } @Specialization(guards = {"isLogicalPrecedence(args)", "args.getLength() == 1"}) - protected Object pMinMaxOneVecLogical(@SuppressWarnings("unused") byte naRm, RArgsValuesAndNames args) { + protected Object pMinMaxOneVecLogical(@SuppressWarnings("unused") boolean naRm, RArgsValuesAndNames args) { return args.getArgument(0); } @Specialization(guards = {"isLogicalPrecedence(args)", "args.getLength() != 1"}) - protected RIntVector pMinMaxLogical(byte naRm, RArgsValuesAndNames args) { + protected RIntVector pMinMaxLogical(boolean naRm, RArgsValuesAndNames args) { return pMinMaxInt(naRm, args); } @Specialization(guards = {"isDoublePrecedence(args)", "args.getLength() == 0"}) @SuppressWarnings("unused") - protected Object pMinMaxNoneVecDouble(byte naRm, RArgsValuesAndNames args) { + protected Object pMinMaxNoneVecDouble(boolean naRm, RArgsValuesAndNames args) { return RDataFactory.createEmptyDoubleVector(); } @Specialization(guards = {"isDoublePrecedence(args)", "args.getLength() == 1"}) @SuppressWarnings("unused") - protected Object pMinMaxOneVecDouble(byte naRm, RArgsValuesAndNames args) { + protected Object pMinMaxOneVecDouble(boolean naRm, RArgsValuesAndNames args) { return args.getArgument(0); } @Specialization(guards = {"isDoublePrecedence(args)", "args.getLength() ==2"}) - protected RDoubleVector pMinMaxTwoDouble(byte naRm, RArgsValuesAndNames args, // + protected RDoubleVector pMinMaxTwoDouble(boolean naRm, RArgsValuesAndNames args, // @Cached("create()") NACheck naCheckX, // @Cached("create()") NACheck naCheckY, // @Cached("create()") CastDoubleNode castX, // @@ -231,7 +243,7 @@ public abstract class PMinMax extends RBuiltinNode { if ((xLength > 1 && xLength < maxLength) || (yLength > 1 && yLength < maxLength)) { RError.warning(RError.SHOW_CALLER2, RError.Message.ARG_RECYCYLED); } - boolean profiledNaRm = naRmProfile.profile(naRm == RRuntime.LOGICAL_TRUE); + boolean profiledNaRm = naRmProfile.profile(naRm); double[] data = new double[maxLength]; int xOffset = 0; int yOffset = 0; @@ -259,7 +271,7 @@ public abstract class PMinMax extends RBuiltinNode { } @Specialization(guards = {"isDoublePrecedence(args)", "args.getLength() > 2"}) - protected RDoubleVector pMinMaxDouble(byte naRm, RArgsValuesAndNames args) { + protected RDoubleVector pMinMaxDouble(boolean naRm, RArgsValuesAndNames args) { int maxLength = convertToVectorAndEnableNACheck(args, getDoubleCastNode()); if (lengthProfile.profile(maxLength == 0)) { return RDataFactory.createEmptyDoubleVector(); @@ -274,7 +286,7 @@ public abstract class PMinMax extends RBuiltinNode { warningAdded = true; } } - boolean profiledNaRm = naRmProfile.profile(naRm == RRuntime.LOGICAL_TRUE); + boolean profiledNaRm = naRmProfile.profile(naRm); double[] data = new double[maxLength]; for (int i = 0; i < maxLength; i++) { double result = semantics.getDoubleStart(); @@ -300,17 +312,17 @@ public abstract class PMinMax extends RBuiltinNode { @Specialization(guards = {"isStringPrecedence(args)", "args.getLength() == 1"}) @SuppressWarnings("unused") - protected Object pMinMaxOneVecString(byte naRm, RArgsValuesAndNames args) { + protected Object pMinMaxOneVecString(boolean naRm, RArgsValuesAndNames args) { return args.getArgument(0); } @Specialization(guards = {"isStringPrecedence(args)", "args.getLength() != 1"}) - protected RStringVector pMinMaxString(byte naRm, RArgsValuesAndNames args) { + protected RStringVector pMinMaxString(boolean naRm, RArgsValuesAndNames args) { int maxLength = convertToVectorAndEnableNACheck(args, getStringCastNode()); if (lengthProfile.profile(maxLength == 0)) { return RDataFactory.createEmptyStringVector(); } else { - boolean profiledNaRm = naRmProfile.profile(naRm == RRuntime.LOGICAL_TRUE); + boolean profiledNaRm = naRmProfile.profile(naRm); String[] data = new String[maxLength]; Object[] argValues = args.getArguments(); byte warningAdded = RRuntime.LOGICAL_FALSE; @@ -322,15 +334,9 @@ public abstract class PMinMax extends RBuiltinNode { } @SuppressWarnings("unused") - @Specialization(guards = "isComplexPrecedence(args)") - protected RComplexVector pMinMaxComplex(byte naRm, RArgsValuesAndNames args) { - throw RError.error(this, RError.Message.INVALID_INPUT_TYPE); - } - - @SuppressWarnings("unused") - @Specialization(guards = "isRawPrecedence(args)") - protected RRawVector pMinMaxRaw(byte naRm, RArgsValuesAndNames args) { - throw RError.error(this, RError.Message.INVALID_INPUT_TYPE); + @Fallback + protected RRawVector pMinMaxRaw(Object naRm, Object args) { + throw RError.error(NO_CALLER, RError.Message.INVALID_INPUT_TYPE); } @RBuiltin(name = "pmax", kind = INTERNAL, parameterNames = {"na.rm", "..."}, behavior = PURE) @@ -367,14 +373,6 @@ public abstract class PMinMax extends RBuiltinNode { return precedence(args) == PrecedenceNode.STRING_PRECEDENCE; } - protected boolean isComplexPrecedence(RArgsValuesAndNames args) { - return precedence(args) == PrecedenceNode.COMPLEX_PRECEDENCE; - } - - protected boolean isRawPrecedence(RArgsValuesAndNames args) { - return precedence(args) == PrecedenceNode.RAW_PRECEDENCE; - } - private int precedence(RArgsValuesAndNames args) { int precedence = -1; Object[] array = args.getArguments(); @@ -386,7 +384,7 @@ public abstract class PMinMax extends RBuiltinNode { protected abstract static class MultiElemStringHandler extends RBaseNode { - public abstract byte executeByte(Object[] argValues, byte naRm, int offset, int ind, int maxLength, byte warning, Object data); + public abstract byte executeByte(Object[] argValues, boolean naRm, int offset, int ind, int maxLength, byte warning, Object data); @Child private MultiElemStringHandler recursiveStringHandler; private final ReduceSemantics semantics; @@ -402,7 +400,7 @@ public abstract class PMinMax extends RBuiltinNode { this.na = na; } - private byte handleString(Object[] argValues, byte naRm, int offset, int ind, int maxLength, byte warning, Object data) { + private byte handleString(Object[] argValues, boolean naRm, int offset, int ind, int maxLength, byte warning, Object data) { if (recursiveStringHandler == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); recursiveStringHandler = insert(MultiElemStringHandlerNodeGen.create(semantics, factory, na)); @@ -411,7 +409,7 @@ public abstract class PMinMax extends RBuiltinNode { } @Specialization - protected byte doStringVectorMultiElem(Object[] argValues, byte naRm, int offset, int ind, int maxLength, byte warning, Object d) { + protected byte doStringVectorMultiElem(Object[] argValues, boolean naRm, int offset, int ind, int maxLength, byte warning, Object d) { String[] data = (String[]) d; byte warningAdded = warning; RAbstractStringVector vec = (RAbstractStringVector) argValues[offset]; @@ -421,7 +419,7 @@ public abstract class PMinMax extends RBuiltinNode { } String result = vec.getDataAt(ind % vec.getLength()); na.enable(result); - if (naRmProfile.profile(naRm == RRuntime.LOGICAL_TRUE)) { + if (naRmProfile.profile(naRm)) { if (na.check(result)) { // the following is meant to eliminate leading NA-s if (offset == argValues.length - 1) { @@ -450,7 +448,7 @@ public abstract class PMinMax extends RBuiltinNode { String current = vec.getDataAt(ind % vec.getLength()); na.enable(current); if (na.check(current)) { - if (naRmProfile.profile(naRm == RRuntime.LOGICAL_TRUE)) { + if (naRmProfile.profile(naRm)) { // skip NA-s continue; } else { 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 4f61514f592b76207e3b56bf3f37b2172a344b72..adf8a6a356681940a902d1eb260b5b205319c18f 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 @@ -22,24 +22,24 @@ */ 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.Message.MUST_BE_STRING_OR_CONNECTION; import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import java.io.File; import java.io.IOException; +import java.net.URISyntaxException; -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.source.Source; import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastIntegerNode; -import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; 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.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; @@ -55,9 +55,7 @@ import com.oracle.truffle.r.runtime.context.RContext; 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.RList; import com.oracle.truffle.r.runtime.data.RNull; -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.env.REnvironment; @@ -97,71 +95,52 @@ public abstract class Parse extends RBuiltinNode { @Child private CastStringNode castStringNode; @Child private CastToVectorNode castVectorNode; - private int castInt(Object n) { - if (castIntNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castIntNode = insert(CastIntegerNodeGen.create(false, false, false)); - } - int result = (int) castIntNode.executeInt(n); - if (RRuntime.isNA(result)) { - result = -1; - } - return result; - } - - private RStringVector castString(Object s) { - if (castStringNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castVectorNode = insert(CastToVectorNodeGen.create(false)); - castStringNode = insert(CastStringNodeGen.create(false, false, false, false)); - } - return (RStringVector) castStringNode.executeString(castVectorNode.execute(s)); + @Override + protected void createCasts(CastBuilder casts) { + // Note: string is captured by the R wrapper and transformed to a file, other types not + casts.arg("conn").mustBe(RConnection.class, MUST_BE_STRING_OR_CONNECTION, "file"); + casts.arg("n").asIntegerVector().findFirst(RRuntime.INT_NA).notNA(-1); + casts.arg("text").allowNull().asStringVector(); + casts.arg("prompt").asStringVector().findFirst("?"); + casts.arg("encoding").mustBe(stringValue()).asStringVector().findFirst(); } + @TruffleBoundary @Specialization - protected Object parse(RConnection conn, Object n, Object text, RAbstractStringVector prompt, Object srcFile, RAbstractStringVector encoding) { - int nAsInt; - if (n != RNull.instance) { - nAsInt = castInt(n); - } else { - nAsInt = -1; + protected Object parse(RConnection conn, int n, @SuppressWarnings("unused") RNull text, String prompt, Object srcFile, String encoding) { + String[] lines; + if (conn == StdConnections.getStdin()) { + throw RError.nyi(this, "parse from stdin not implemented"); } - Object textVec = text; - if (textVec != RNull.instance) { - textVec = castString(textVec); + try (RConnection openConn = conn.forceOpen("r")) { + lines = openConn.readLines(0, false, false); + } catch (IOException ex) { + throw RError.error(this, RError.Message.PARSE_ERROR); } - return doParse(conn, nAsInt, textVec, prompt, srcFile, encoding); + return doParse(conn, n, lines, prompt, srcFile, encoding); } @TruffleBoundary + @Specialization + protected Object parse(RConnection conn, int n, RAbstractStringVector text, String prompt, Object srcFile, String encoding) { + return doParse(conn, n, text.materialize().getDataWithoutCopying(), prompt, srcFile, encoding); + } + @SuppressWarnings("unused") - private Object doParse(RConnection conn, int n, Object textVec, RAbstractStringVector prompt, Object srcFile, RAbstractStringVector encoding) { - String[] lines; - if (textVec == RNull.instance) { - if (conn == StdConnections.getStdin()) { - throw RError.nyi(this, "parse from stdin not implemented"); - } - try (RConnection openConn = conn.forceOpen("r")) { - lines = openConn.readLines(0, false, false); - } catch (IOException ex) { - throw RError.error(this, RError.Message.PARSE_ERROR); - } - } else { - lines = ((RStringVector) textVec).getDataWithoutCopying(); - } + private Object doParse(RConnection conn, int n, String[] lines, String prompt, Object srcFile, String encoding) { String coalescedLines = coalesce(lines); if (coalescedLines.length() == 0 || n == 0) { - return RDataFactory.createExpression(RDataFactory.createList()); + return RDataFactory.createExpression(new Object[0]); } try { Source source = srcFile != RNull.instance ? createSource(srcFile, coalescedLines) : createSource(conn, coalescedLines); RExpression exprs = RContext.getEngine().parse(null, source); - if (n > 0 && n > exprs.getLength()) { - RList list = exprs.getList(); - Object[] listData = list.getDataCopy(); + if (n > 0 && n < exprs.getLength()) { Object[] subListData = new Object[n]; - System.arraycopy(listData, 0, subListData, 0, n); - exprs = RDataFactory.createExpression(RDataFactory.createList(subListData)); + for (int i = 0; i < n; i++) { + subListData[i] = exprs.getDataAt(i); + } + exprs = RDataFactory.createExpression(subListData); } // Handle the required R attributes if (srcFile instanceof REnvironment) { @@ -207,7 +186,9 @@ public abstract class Parse extends RBuiltinNode { } else { path = fileName; } - return createFileSource(path, coalescedLines); + Source result = createFileSource(path, coalescedLines); + assert result != null : "Source created from environment should not be null"; + return result; } else { return Source.newBuilder(coalescedLines).name("<parse>").mimeType(RRuntime.R_APP_MIME).build(); } @@ -228,7 +209,12 @@ public abstract class Parse extends RBuiltinNode { } private static Source createFileSource(String path, String chars) { - return RSource.fromFileName(chars, path); + try { + return RSource.fromFileName(chars, path); + } 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(); + } } private static void addAttributes(RExpression exprs, Source source, REnvironment srcFile) { 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 2cb7f66bef9630cdd904f654fde6b68595e6cdfa..cdb0a92d5d643a58da3ac301a17377e81323104e 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 @@ -22,28 +22,27 @@ */ 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.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.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.PrimitiveValueProfile; import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.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.RList; 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.RVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; @RBuiltin(name = "paste", kind = INTERNAL, parameterNames = {"", "sep", "collapse"}, behavior = PURE) public abstract class Paste extends RBuiltinNode { @@ -59,22 +58,15 @@ public abstract class Paste extends RBuiltinNode { @Child private CastStringNode castCharacterNode; private final ValueProfile lengthProfile = PrimitiveValueProfile.createEqualityProfile(); - private final ConditionProfile vectorOrSequence = ConditionProfile.createBinaryProfile(); private final ConditionProfile reusedResultProfile = ConditionProfile.createBinaryProfile(); private final BranchProfile nonNullElementsProfile = BranchProfile.create(); private final BranchProfile onlyNullElementsProfile = BranchProfile.create(); - private RStringVector castCharacter(Object o) { - if (asCharacterNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - asCharacterNode = insert(AsCharacterNodeGen.create(null)); - } - Object ret = asCharacterNode.execute(o); - if (ret instanceof String) { - return RDataFactory.createStringVector((String) ret); - } else { - return (RStringVector) ret; - } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg(0).mustBe(RAbstractListVector.class); + casts.arg("sep").asStringVector().findFirst(Message.INVALID_SEPARATOR); + casts.arg("collapse").allowNull().mustBe(stringValue()).asStringVector().findFirst(); } /** @@ -85,18 +77,20 @@ public abstract class Paste extends RBuiltinNode { private RStringVector castCharacterVector(Object o) { if (castCharacterNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - castCharacterNode = insert(CastStringNodeGen.create(false, true, false, false)); + castCharacterNode = insert(CastStringNodeGen.create(false, false, false)); } Object ret = castCharacterNode.executeString(o); if (ret instanceof String) { return RDataFactory.createStringVector((String) ret); + } else if (ret == RNull.instance) { + return RDataFactory.createEmptyStringVector(); } else { - return (RStringVector) ret; + return (RStringVector) ((RStringVector) ret).copyDropAttributes(); } } @Specialization - protected RStringVector pasteList(RList values, String sep, @SuppressWarnings("unused") RNull collapse) { + protected RStringVector pasteList(RAbstractListVector values, String sep, @SuppressWarnings("unused") RNull collapse) { int length = lengthProfile.profile(values.getLength()); if (hasNonNullElements(values, length)) { String[] result = pasteListElements(values, sep, length); @@ -106,27 +100,18 @@ public abstract class Paste extends RBuiltinNode { } } - @Specialization(guards = "!isRNull(collapse)") - protected String pasteList(RList values, String sep, Object collapse, // - @Cached("createBinaryProfile()") ConditionProfile collapseIsVectorProfile) { + @Specialization + protected String pasteList(RAbstractListVector values, String sep, String collapse) { int length = lengthProfile.profile(values.getLength()); if (hasNonNullElements(values, length)) { String[] result = pasteListElements(values, sep, length); - String collapseString; - if (collapse instanceof String) { - collapseString = (String) collapse; - } else if (collapseIsVectorProfile.profile(collapse instanceof RAbstractStringVector)) { - collapseString = ((RAbstractStringVector) collapse).getDataAt(0); - } else { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "collapse"); - } - return collapseString(result, collapseString); + return collapseString(result, collapse); } else { return ""; } } - private boolean hasNonNullElements(RList values, int length) { + private boolean hasNonNullElements(RAbstractListVector values, int length) { for (int i = 0; i < length; i++) { if (values.getDataAt(i) != RNull.instance) { nonNullElementsProfile.enter(); @@ -137,17 +122,12 @@ public abstract class Paste extends RBuiltinNode { return false; } - private String[] pasteListElements(RList values, String sep, int length) { + private String[] pasteListElements(RAbstractListVector values, String sep, int length) { String[][] converted = new String[length][]; int maxLength = 1; for (int i = 0; i < length; i++) { Object element = values.getDataAt(i); - String[] array; - if (vectorOrSequence.profile(element instanceof RVector || element instanceof RSequence)) { - array = castCharacterVector(element).getDataWithoutCopying(); - } else { - array = castCharacter(element).getDataWithoutCopying(); - } + String[] array = castCharacterVector(element).getDataWithoutCopying(); maxLength = Math.max(maxLength, array.length); converted[i] = array.length == 0 ? ONE_EMPTY_STRING : array; } 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 e3a56703d4d7d0d651c958482eaf9520d6a762e0..18369a4686c8a6ee3b195d21aa536a32b4de6931 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 @@ -22,11 +22,12 @@ */ 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.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.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RList; @@ -38,18 +39,16 @@ import com.oracle.truffle.r.runtime.data.RList; @RBuiltin(name = "paste0", kind = INTERNAL, parameterNames = {"list", "collapse"}, behavior = PURE) public abstract class Paste0 extends RBuiltinNode { - @Child private Paste pasteNode; + @Child private Paste pasteNode = PasteNodeGen.create(null); - private Object paste(RList values, Object collapse) { - if (pasteNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - pasteNode = insert(PasteNodeGen.create(null)); - } - return pasteNode.executeList(values, "", collapse); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("list").mustBe(RList.class); + casts.arg("collapse").allowNull().mustBe(stringValue()).asStringVector().findFirst(); } @Specialization protected Object paste0(RList values, Object collapse) { - return paste(values, collapse); + return pasteNode.executeList(values, "", collapse); } } 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 d8ce346727888f085b67a939ac392c5af4aef715..640b323010095b81810560ba398ca39a4b9028ea 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 @@ -22,13 +22,14 @@ */ 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.builtins.RBehavior.IO; 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.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -37,6 +38,11 @@ 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 { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("path").mustBe(stringValue()); + } + @Specialization @TruffleBoundary protected Object doPathExpand(RAbstractStringVector vec) { @@ -47,10 +53,4 @@ public abstract class PathExpand extends RBuiltinNode { } return RDataFactory.createStringVector(results, RDataFactory.COMPLETE_VECTOR); } - - @Specialization - @TruffleBoundary - protected Object doPathExpandGeneric(@SuppressWarnings("unused") Object path) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "path"); - } } 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 db9729cdf6736b4720305df90f902393d8cb17e4..fdcad6132cc24b5119b071873ca097ca83765435 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 @@ -22,14 +22,19 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +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.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; -import com.oracle.truffle.api.dsl.Fallback; +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.CastBuilder; 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.builtins.RBuiltinKind; import com.oracle.truffle.r.runtime.context.RContext; @@ -37,24 +42,34 @@ 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(); - // TODO: implement inline caching + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("name").defaultError(Message.STRING_ARGUMENT_REQUIRED).mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst(); + } + + @Specialization(guards = "name == cachedName") + protected RFunction primitiveCached(@SuppressWarnings("unused") String name, + @Cached("name") @SuppressWarnings("unused") String cachedName, + @Cached("lookup(name)") RFunction function) { + return function; + } - @Specialization + @Specialization(contains = "primitiveCached") protected RFunction primitive(String name) { + RFunction function = lookup(name); + return function; + } + + @TruffleBoundary + 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); } - - // .Primitive function is validated return function; } - - @Fallback - protected RFunction primitive(@SuppressWarnings("unused") Object name) { - throw RError.error(this, RError.Message.STRING_ARGUMENT_REQUIRED); - } } 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 cfb8266c0508dbce669831f572566bec85c5a3be..e9986082710a85a492a3ea76c8c4c7350985c88c 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 @@ -22,11 +22,16 @@ */ 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.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notIntNA; +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.OFF; import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; -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.frame.VirtualFrame; @@ -35,7 +40,7 @@ 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.PrintParameters; import com.oracle.truffle.r.nodes.builtin.base.printer.ValuePrinterNode; -import com.oracle.truffle.r.nodes.builtin.base.printer.ValuePrinterNodeGen; +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.context.RContext; @@ -53,21 +58,30 @@ public class PrintFunctions { private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); - @Child private ValuePrinterNode valuePrinter = ValuePrinterNodeGen.create(); + @Child private ValuePrinterNode valuePrinter = new ValuePrinterNode(); @Override protected void createCasts(CastBuilder casts) { - super.createCasts(casts); - casts.firstBoolean(2); - casts.firstBoolean(5); - casts.firstBoolean(7); - casts.firstBoolean(8); + 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("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("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("noOpt").defaultError(RError.Message.GENERIC, "invalid 'tryS4' internal argument").asLogicalVector().findFirst().notNA().map(toBoolean()); } - @TruffleBoundary @Specialization(guards = "!isS4(o)") - protected Object printDefault(Object o, Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, boolean noOpt) { - valuePrinter.executeString(o, digits, quote, naPrint, printGap, right, max, useSource, noOpt); + protected Object printDefault(VirtualFrame frame, Object o, Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, boolean noOpt) { + valuePrinter.execute(frame, o, digits, quote, naPrint, printGap, right, max, useSource, noOpt); return o; } @@ -75,7 +89,6 @@ public class PrintFunctions { return ReadVariableNode.lookupFunction("show", frame); } - @SuppressWarnings("unused") @Specialization(guards = "isS4(o)") protected Object printDefaultS4(VirtualFrame frame, RTypedValue o, Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, boolean noOpt, // @Cached("createShowFunction(frame)") RFunction showFunction) { @@ -83,7 +96,7 @@ public class PrintFunctions { // S4 should only be called in case noOpt is true RContext.getEngine().evalFunction(showFunction, null, null, null, o); } else { - printDefault(showFunction, digits, quote, naPrint, printGap, right, max, useSource, noOpt); + printDefault(frame, showFunction, digits, quote, naPrint, printGap, right, max, useSource, noOpt); } return null; } @@ -96,12 +109,19 @@ public class PrintFunctions { @RBuiltin(name = "print.function", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "useSource", "..."}, behavior = IO) public abstract static class PrintFunction extends RBuiltinNode { - @Child private ValuePrinterNode valuePrinter = ValuePrinterNodeGen.create(); + @Child private ValuePrinterNode valuePrinter = new ValuePrinterNode(); + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(instanceOf(RFunction.class)); + + casts.arg("useSource").defaultError(RError.Message.INVALID_ARGUMENT, "useSource").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + } @SuppressWarnings("unused") @Specialization - protected RFunction printFunction(RFunction x, byte useSource, RArgsValuesAndNames extra) { - valuePrinter.executeString(x, PrintParameters.getDefaultDigits(), true, RString.valueOf(RRuntime.STRING_NA), 1, false, PrintParameters.getDefaultMaxPrint(), true, false); + protected RFunction printFunction(VirtualFrame frame, RFunction x, boolean useSource, RArgsValuesAndNames extra) { + valuePrinter.execute(frame, x, PrintParameters.getDefaultDigits(), true, RString.valueOf(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/Quantifier.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java new file mode 100644 index 0000000000000000000000000000000000000000..80a9bc80086da484cc60f2ace5e73e0aacafe554 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java @@ -0,0 +1,161 @@ +/* + * 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.builtin.base; + +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.toBoolean; + +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.nodes.ExplodeLoop; +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.unary.CastNode; +import com.oracle.truffle.r.nodes.unary.TypeofNode; +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.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.model.RAbstractLogicalVector; +import com.oracle.truffle.r.runtime.ops.na.NACheck; + +public abstract class Quantifier extends RBuiltinNode { + protected static final int MAX_CACHED_LENGTH = 10; + + private final NACheck naCheck = NACheck.create(); + private final BranchProfile trueBranch = BranchProfile.create(); + private final BranchProfile falseBranch = BranchProfile.create(); + + @Child private TypeofNode typeofNode = com.oracle.truffle.r.nodes.unary.TypeofNodeGen.create(); + private final Function<Object, String> argTypeName = arg -> typeofNode.execute(arg).getName(); + + @Children private final CastNode[] argCastNodes = new CastNode[MAX_CACHED_LENGTH]; + + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{RArgsValuesAndNames.EMPTY, RRuntime.LOGICAL_FALSE}; + } + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); + } + + private void createArgCast(int index) { + CastBuilder argCastBuilder = new CastBuilder(); + argCastBuilder.arg(0).allowNull().shouldBe(integerValue().or(logicalValue()), RError.Message.COERCING_ARGUMENT, argTypeName, "logical").asLogicalVector(); + argCastNodes[index] = insert(argCastBuilder.getCasts()[0]); + } + + protected boolean emptyVectorResult() { + throw RInternalError.shouldNotReachHere("should be overridden"); + } + + @Specialization + protected byte op(@SuppressWarnings("unused") RNull vector, @SuppressWarnings("unused") boolean naRm) { + return RRuntime.asLogical(emptyVectorResult()); + } + + @Specialization + protected byte op(@SuppressWarnings("unused") RMissing vector, @SuppressWarnings("unused") boolean naRm) { + return RRuntime.asLogical(emptyVectorResult()); + } + + @Specialization(limit = "1", guards = {"cachedLength == args.getLength()", "cachedLength < MAX_CACHED_LENGTH"}) + @ExplodeLoop + protected byte opCachedLength(RArgsValuesAndNames args, boolean naRm, // + @Cached("args.getLength()") int cachedLength) { + Object[] arguments = args.getArguments(); + + byte result = RRuntime.asLogical(emptyVectorResult()); + for (int i = 0; i < cachedLength; i++) { + Object argValue = arguments[i]; + byte v = processArgument(argValue, i, naRm); + if (v == RRuntime.asLogical(!emptyVectorResult())) { + return RRuntime.asLogical(!emptyVectorResult()); + } else if (v == RRuntime.LOGICAL_NA) { + result = RRuntime.LOGICAL_NA; + } + } + return result; + } + + @Specialization(contains = "opCachedLength") + protected byte op(RArgsValuesAndNames args, boolean naRm) { + boolean profiledNaRm = naRm; + + byte result = RRuntime.asLogical(emptyVectorResult()); + for (Object argValue : args.getArguments()) { + byte v = processArgument(argValue, 0, profiledNaRm); + if (v == RRuntime.asLogical(!emptyVectorResult())) { + return RRuntime.asLogical(!emptyVectorResult()); + } else if (v == RRuntime.LOGICAL_NA) { + result = RRuntime.LOGICAL_NA; + } + } + return result; + } + + private byte processArgument(Object argValue, int index, boolean naRm) { + byte result = RRuntime.asLogical(emptyVectorResult()); + if (argValue != RNull.instance) { + if (argCastNodes[index] == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + createArgCast(index); + } + Object castValue = argCastNodes[index].execute(argValue); + if (castValue instanceof RAbstractLogicalVector) { + RAbstractLogicalVector vector = (RAbstractLogicalVector) castValue; + naCheck.enable(vector); + for (int i = 0; i < vector.getLength(); i++) { + byte b = vector.getDataAt(i); + if (!naRm && naCheck.check(b)) { + result = RRuntime.LOGICAL_NA; + } else if (b == RRuntime.asLogical(!emptyVectorResult())) { + trueBranch.enter(); + return RRuntime.asLogical(!emptyVectorResult()); + } + } + } else { + byte b = (byte) castValue; + naCheck.enable(true); + if (!naRm && naCheck.check(b)) { + result = RRuntime.LOGICAL_NA; + } else if (b == RRuntime.asLogical(!emptyVectorResult())) { + trueBranch.enter(); + return RRuntime.asLogical(!emptyVectorResult()); + } + } + } + falseBranch.enter(); + return result; + } + +} 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 17aa680ce81c3782274c132ced48f1b299217f6d..7ccf2fb1894bc50ef24ca7f765e3913e03b10cea 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 @@ -12,12 +12,12 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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.INTERNAL; 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.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; @@ -30,14 +30,15 @@ import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "quit", visibility = OFF, kind = INTERNAL, parameterNames = {"save", "status", "runLast"}, behavior = COMPLEX) public abstract class Quit extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1); + casts.arg("save").mustBe(stringValue(), RError.Message.QUIT_ASK).asStringVector().findFirst(); + casts.arg("status").asIntegerVector().findFirst(); + casts.arg("runLast").asLogicalVector().findFirst(); } private SA_TYPE checkSaveValue(String save) throws RError { @@ -51,20 +52,20 @@ public abstract class Quit extends RBuiltinNode { @Specialization @TruffleBoundary - protected Object doQuit(RAbstractStringVector saveArg, final int status, final byte runLastIn) { + 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); return RNull.instance; } - String save = saveArg.getDataAt(0); RStartParams.SA_TYPE ask = checkSaveValue(save); if (ask == SA_TYPE.SAVEASK && !RContext.getInstance().getConsoleHandler().isInteractive()) { RError.warning(this, RError.Message.QUIT_ASK_INTERACTIVE); } if (status == RRuntime.INT_NA) { RError.warning(this, RError.Message.QUIT_INVALID_STATUS); + runLast = RRuntime.LOGICAL_FALSE; } - byte runLast = runLastIn; if (runLast == RRuntime.LOGICAL_NA) { RError.warning(this, RError.Message.QUIT_INVALID_RUNLAST); runLast = RRuntime.LOGICAL_FALSE; @@ -73,12 +74,4 @@ public abstract class Quit extends RBuiltinNode { throw RInternalError.shouldNotReachHere("cleanup returned"); } - @SuppressWarnings("unused") - @Fallback - protected Object doQuit(Object saveArg, Object status, Object runLast) { - if (RRuntime.asString(saveArg) == null) { - throw RError.error(this, RError.Message.QUIT_ASK); - } - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); - } } 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 40dd919e5b331e986751e1b0e6ecf6562665bed8..f3d805fcebb1295617aaf6fd4b0fb5e0715c9339 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 @@ -25,49 +25,51 @@ 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.RASTUtils; -import com.oracle.truffle.r.nodes.access.ConstantNode; -import com.oracle.truffle.r.nodes.access.ReadVariadicComponentNode; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; 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.RLanguage; -import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RPromise; -import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.data.RPromise.Closure; +import com.oracle.truffle.r.runtime.data.RShareable; @RBuiltin(name = "quote", nonEvalArgs = 0, kind = PRIMITIVE, parameterNames = {"expr"}, behavior = PURE) public abstract class Quote extends RBuiltinNode { + protected static final int LIMIT = 3; + + private final ConditionProfile shareableProfile = ConditionProfile.createBinaryProfile(); + public abstract Object execute(RPromise expr); - private final ConditionProfile rvn = ConditionProfile.createBinaryProfile(); - private final ConditionProfile rvcn = ConditionProfile.createBinaryProfile(); - private final ConditionProfile cn = ConditionProfile.createBinaryProfile(); + /** + * Creates a shared permanent language so that it can be cached and repeatedly returned as the + * result. + */ + protected final Object cachedCreateLanguage(Closure closure) { + Object result = createLanguage(closure); + if (shareableProfile.profile(result instanceof RShareable)) { + ((RShareable) result).makeSharedPermanent(); + } + return result; + } - @Specialization - protected RLanguage doQuote(@SuppressWarnings("unused") RMissing arg) { - throw RError.error(this, RError.Message.ARGUMENTS_PASSED_0_1, getRBuiltin().name()); + protected static Object createLanguage(Closure closure) { + return RASTUtils.createLanguageElement(closure.getExpr().asRSyntaxNode()); } - @Specialization - protected Object doQuote(RPromise expr) { - // GnuR creates symbols for simple variables and actual values for constants - RNode node = (RNode) expr.getRep(); - RNode unode = (RNode) RASTUtils.unwrap(node); - if (rvn.profile(unode instanceof ReadVariableNode)) { - return RASTUtils.createRSymbol(unode); - } else if (cn.profile(unode instanceof ConstantNode)) { - ConstantNode cnode = (ConstantNode) unode; - return cnode.getValue(); - } else if (rvcn.profile(unode instanceof ReadVariadicComponentNode)) { - return RASTUtils.createRSymbol(unode); - } else { - return RDataFactory.createLanguage(unode); - } + @SuppressWarnings("unused") + @Specialization(limit = "LIMIT", guards = "cachedClosure == expr.getClosure()") + protected Object quoteCached(RPromise expr, + @Cached("expr.getClosure()") Closure cachedClosure, + @Cached("cachedCreateLanguage(cachedClosure)") Object language) { + return language; + } + + @Specialization(contains = "quoteCached") + protected Object quote(RPromise expr) { + return createLanguage(expr.getClosure()); } } 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 8c7c8ca2f7e10e958b0ea21955b58b896630a6ea..eb22afec1bbb34980ca423f685bef8f6fe6cfd2e 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 @@ -22,53 +22,55 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +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; +import static com.oracle.truffle.r.runtime.RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION; import static com.oracle.truffle.r.runtime.RVisibility.OFF; 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.CompilerDirectives; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.RIntVector; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.rng.RRNG; public class RNGFunctions { @RBuiltin(name = "set.seed", visibility = OFF, kind = INTERNAL, parameterNames = {"seed", "kind", "normal.kind"}, behavior = MODIFIES_STATE) public abstract static class SetSeed extends RBuiltinNode { - @SuppressWarnings("unused") - @Specialization - protected RNull setSeed(double seed, RNull kind, RNull normKind) { - doSetSeed((int) seed, RRNG.NO_KIND_CHANGE, RRNG.NO_KIND_CHANGE); - return RNull.instance; + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("seed").allowNull().mustBe(numericValue(), SHOW_CALLER, SEED_NOT_VALID_INT).asIntegerVector().findFirst(); + Casts.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); } @SuppressWarnings("unused") @Specialization - protected RNull setSeed(double seed, RAbstractIntVector kind, RNull normKind) { - doSetSeed((int) seed, kind.getDataAt(0), RRNG.NO_KIND_CHANGE); + protected RNull setSeed(int seed, int kind, RNull normKind) { + doSetSeed(seed, kind, RRNG.NO_KIND_CHANGE); return RNull.instance; } @SuppressWarnings("unused") @Specialization - protected RNull setSeed(RNull seed, RNull kind, RNull normKind) { - doSetSeed(RRNG.timeToSeed(), RRNG.NO_KIND_CHANGE, RRNG.NO_KIND_CHANGE); + protected RNull setSeed(RNull seed, int kind, RNull normKind) { + doSetSeed(RRNG.timeToSeed(), kind, RRNG.NO_KIND_CHANGE); return RNull.instance; } - @SuppressWarnings("unused") - @Specialization - protected RNull setSeed(byte seed, RNull kind, RNull normKind) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.SEED_NOT_VALID_INT); - } - private static void doSetSeed(int newSeed, int kind, int normKind) { RRNG.doSetSeed(newSeed, kind, normKind); } @@ -77,25 +79,28 @@ public class RNGFunctions { @RBuiltin(name = "RNGkind", kind = INTERNAL, parameterNames = {"kind", "normkind"}, behavior = MODIFIES_STATE) public abstract static class RNGkind extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + Casts.kindInteger(casts, "kind", INVALID_ARGUMENT, "kind"); + Casts.kindInteger(casts, "normkind", INVALID_NORMAL_TYPE_IN_RGNKIND); + } + @Specialization - protected RIntVector doRNGkind(Object kind, Object normKind) { + protected RIntVector doRNGkind(int kind, int normKind) { RRNG.getRNGState(); RIntVector result = getCurrent(); - int kindChange = checkType(kind, "kind"); - int normKindChange = checkType(normKind, "normkind"); - RRNG.doRNGKind(kindChange, normKindChange); + RRNG.doRNGKind(kind, normKind); return result; } - private int checkType(Object kind, String name) { - if (!(kind == RNull.instance || kind instanceof RIntVector || kind instanceof Integer)) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, name); - } - return kind == RNull.instance ? RRNG.NO_KIND_CHANGE : kind instanceof Integer ? (Integer) kind : ((RAbstractIntVector) kind).getDataAt(0); - } - private static RIntVector getCurrent() { return RDataFactory.createIntVector(new int[]{RRNG.currentKindAsInt(), RRNG.currentNormKindAsInt()}, RDataFactory.COMPLETE_VECTOR); } } + + private static final class Casts { + public static void kindInteger(CastBuilder casts, String name, Message error, Object... messageArgs) { + casts.arg(name).mapNull(constant(RRNG.NO_KIND_CHANGE)).mustBe(numericValue(), SHOW_CALLER, error, messageArgs).asIntegerVector().findFirst(); + } + } } 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 5db642574c7f1e5925a1260bc6177e5bca5c3ce6..8176fec9cefbc7e714de3fe4a58a821c20841f55 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 @@ -22,6 +22,7 @@ */ 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.RDispatch.SUMMARY_GROUP_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -54,7 +55,8 @@ public abstract class Range extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.firstBoolean(1).firstBoolean(2); + casts.arg("na.rm").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("finite").asLogicalVector().findFirst().map(toBoolean()); } @Override @@ -63,13 +65,13 @@ public abstract class Range extends RBuiltinNode { } @Specialization(guards = "args.getLength() == 1") - protected RVector rangeLengthOne(RArgsValuesAndNames args, boolean naRm, boolean finite) { + protected RVector<?> rangeLengthOne(RArgsValuesAndNames args, boolean naRm, boolean finite) { Object min = minReduce.executeReduce(args.getArgument(0), naRm, finite); Object max = maxReduce.executeReduce(args.getArgument(0), naRm, finite); return createResult(min, max); } - private static RVector createResult(Object min, Object max) { + private static RVector<?> createResult(Object min, Object max) { if (min instanceof Integer) { return RDataFactory.createIntVector(new int[]{(Integer) min, (Integer) max}, false); } else { @@ -78,7 +80,7 @@ public abstract class Range extends RBuiltinNode { } @Specialization(contains = "rangeLengthOne") - protected RVector range(RArgsValuesAndNames args, boolean naRm, boolean finite, // + protected RVector<?> range(RArgsValuesAndNames args, boolean naRm, boolean finite, // @Cached("create()") Combine combine) { Object combined = combine.executeCombine(args); Object min = minReduce.executeReduce(combined, naRm, finite); 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 808450ebf3bd2d4012d71e35239fd801358bafde..f855a8a7742784c2890d0ca6347425d535591664 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 @@ -12,23 +12,38 @@ */ 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.gte0; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.intNA; +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.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; +import static com.oracle.truffle.r.runtime.RError.Message.UNIMPLEMENTED_TYPE_IN_GREATER; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; 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.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.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.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.RRawVector; 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.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "rank", kind = INTERNAL, parameterNames = {"x", "len", "ties.method"}, behavior = PURE) @@ -36,59 +51,58 @@ public abstract class Rank extends RBuiltinNode { @Child private Order.OrderVector1Node orderVector1Node; @Child private Order.CmpNode orderCmpNode; + private final BranchProfile errorProfile = BranchProfile.create(); private static final Object rho = new Object(); private enum TiesKind { AVERAGE, MAX, - MIN; + MIN } @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1); + // @formatter:off + 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); + // 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())); + // 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(); + // @formatter:on } private Order.OrderVector1Node initOrderVector1() { if (orderVector1Node == null) { - orderVector1Node = insert(OrderVector1NodeGen.create()); + CompilerDirectives.transferToInterpreterAndInvalidate(); + orderVector1Node = insert(OrderVector1NodeGen.create(false)); } return orderVector1Node; } private Order.CmpNode initOrderCmp() { if (orderCmpNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); orderCmpNode = insert(CmpNodeGen.create()); } return orderCmpNode; } @Specialization - protected Object rank(RAbstractVector xa, int n, RAbstractStringVector tiesMethod) { - if (n < 0 || RRuntime.isNA(n)) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "length(xx)"); - } - if (xa instanceof RRawVector) { - throw RError.error(this, RError.Message.RAW_SORT); + protected Object rank(RAbstractVector xa, int inN, String tiesMethod) { + int n = inN; + if (n > xa.getLength()) { + errorProfile.enter(); + n = xa.getLength(); + RError.warning(SHOW_CALLER, RANK_LARGE_N); } - TiesKind tiesKind; - switch (tiesMethod.getDataAt(0)) { - case "average": - tiesKind = TiesKind.AVERAGE; - break; - - case "max": - tiesKind = TiesKind.MAX; - break; - - case "min": - tiesKind = TiesKind.MIN; - break; - default: - throw RError.error(this, RError.Message.GENERIC, "invalid ties.method for rank() [should never happen]"); - } + TiesKind tiesKind = getTiesKind(tiesMethod); int[] ik = null; double[] rk = null; if (tiesKind == TiesKind.AVERAGE) { @@ -134,4 +148,18 @@ public abstract class Rank extends RBuiltinNode { return RDataFactory.createIntVector(ik, RDataFactory.COMPLETE_VECTOR); } } + + private TiesKind getTiesKind(String tiesMethod) { + switch (tiesMethod) { + case "average": + return TiesKind.AVERAGE; + case "max": + return TiesKind.MAX; + case "min": + return TiesKind.MIN; + default: + errorProfile.enter(); + throw RError.error(NO_CALLER, 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 2d3786c3cc50fb170e9896fef60f6bec5480126a..2e280d369e14bd37c98b97e0235e515ebc1d58d6 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 @@ -22,18 +22,22 @@ */ 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.nodes.builtin.CastBuilder.Predef.notEmpty; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte; 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.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.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.RRawVector; @@ -48,6 +52,12 @@ public class RawFunctions { @RBuiltin(name = "charToRaw", kind = INTERNAL, parameterNames = "x", behavior = PURE) public abstract static class CharToRaw extends RBuiltinNode { + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").defaultError(RError.Message.ARG_MUST_BE_CHARACTER_VECTOR_LENGTH_ONE).mustBe(stringValue()).asStringVector().mustBe(notEmpty()); + } + @Specialization protected RRawVector charToRaw(RAbstractStringVector x) { if (x.getLength() > 1) { @@ -61,21 +71,21 @@ public class RawFunctions { return RDataFactory.createRawVector(data); } - @Fallback - protected Object charToRaw(@SuppressWarnings("unused") Object x) { - throw RError.error(this, RError.Message.ARG_MUST_BE_CHARACTER_VECTOR_LENGTH_ONE); - } } @RBuiltin(name = "rawToChar", kind = INTERNAL, parameterNames = {"x", "multiple"}, behavior = PURE) public abstract static class RawToChar extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + 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()); + } + @Specialization - protected RStringVector rawToChar(RAbstractRawVector x, byte multiple) { - if (RRuntime.isNA(multiple)) { - throw RError.error(this, RError.Message.INVALID_LOGICAL, "multiple"); - } + @TruffleBoundary + protected RStringVector rawToChar(RAbstractRawVector x, boolean multiple) { RStringVector result; - if (RRuntime.fromLogical(multiple)) { + if (multiple) { String[] data = new String[x.getLength()]; for (int i = 0; i < data.length; i++) { data[i] = new String(new byte[]{x.getDataAt(i).getValue()}); @@ -95,28 +105,19 @@ public class RawFunctions { return result; } - @SuppressWarnings("unused") - @Fallback - protected Object rawToChar(Object x, Object multiple) { - throw RError.error(this, RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x"); - } } @RBuiltin(name = "rawShift", kind = INTERNAL, parameterNames = {"x", "n"}, behavior = PURE) public abstract static class RawShift extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.firstIntegerWithError(1, null, null); + 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))); } @Specialization protected RRawVector rawShift(RAbstractRawVector x, int n, // - @Cached("createBinaryProfile()") ConditionProfile negativeShiftProfile, // - @Cached("create()") BranchProfile errorProfile) { - if (n < -8 || n > 8) { - errorProfile.enter(); - throw RError.error(this, RError.Message.MUST_BE_SMALL_INT, "shift"); - } + @Cached("createBinaryProfile()") ConditionProfile negativeShiftProfile) { byte[] data = new byte[x.getLength()]; if (negativeShiftProfile.profile(n < 0)) { for (int i = 0; i < data.length; i++) { @@ -130,11 +131,6 @@ public class RawFunctions { return RDataFactory.createRawVector(data); } - @SuppressWarnings("unused") - @Fallback - protected Object charToRaw(Object x, Object n) { - throw RError.error(this, RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR); - } } // TODO the rest of the functions 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 3bc66597230371ffa0fbd99c3a8bf37ade867c2d..2d9f66c7dec0eed51f9b65ea35d070586a56ca93 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -33,8 +34,8 @@ import java.util.Map; import java.util.Set; 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.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.DCF; import com.oracle.truffle.r.runtime.RError; @@ -50,15 +51,20 @@ 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 { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("conn").mustBe(RConnection.class); + casts.arg("fields").mapNull(emptyStringVector()).asStringVector(); + casts.arg("keepwhite").mapNull(emptyStringVector()).asStringVector(); + } + @Specialization @TruffleBoundary - protected RStringVector doReadDCF(RConnection conn, Object fieldsObj, Object keepWhiteObj) { - RAbstractStringVector fields = fieldsObj == RNull.instance ? null : (RAbstractStringVector) RRuntime.asAbstractVector(fieldsObj); - RAbstractStringVector keepWhite = keepWhiteObj == RNull.instance ? null : (RAbstractStringVector) RRuntime.asAbstractVector(keepWhiteObj); + protected RStringVector doReadDCF(RConnection conn, RAbstractStringVector fields, RAbstractStringVector keepWhite) { DCF dcf = null; try (RConnection openConn = conn.forceOpen("r")) { Set<String> keepWhiteSet = null; - if (keepWhite != null) { + if (keepWhite.getLength() > 0) { keepWhiteSet = new HashSet<>(keepWhite.getLength()); for (int i = 0; i < keepWhite.getLength(); i++) { keepWhiteSet.add(keepWhite.getDataAt(i)); @@ -116,7 +122,7 @@ public abstract class ReadDCF extends RBuiltinNode { } private static boolean needField(String fieldName, RAbstractStringVector fields) { - if (fields == null) { + if (fields.getLength() == 0) { return true; } for (int i = 0; i < fields.getLength(); i++) { @@ -127,9 +133,4 @@ public abstract class ReadDCF extends RBuiltinNode { return false; } - @SuppressWarnings("unused") - @Fallback - protected RStringVector doReadDCF(Object conn, Object fields, Object keepWhite) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); - } } 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 91d68a96774c913b87f198d21aced47759a51838..dc155922033fcc9e97304de53e5470078165a209 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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.INTERNAL; @@ -30,23 +31,25 @@ import java.io.FileNotFoundException; import java.io.IOException; 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.CastBuilder; 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.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -@RBuiltin(name = "readRenviron", visibility = OFF, kind = INTERNAL, parameterNames = "path", behavior = COMPLEX) +@RBuiltin(name = "readRenviron", visibility = OFF, kind = INTERNAL, parameterNames = "x", behavior = COMPLEX) public abstract class ReadREnviron extends RBuiltinNode { - @Specialization(guards = "lengthOneCVector(vec)") + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.ARGUMENT_MUST_BE_STRING, "x").asStringVector().findFirst(); + } + @TruffleBoundary - protected Object doReadEnviron(RAbstractStringVector vec) { - String path = Utils.tildeExpand(vec.getDataAt(0)); + @Specialization + protected Object doReadEnviron(String path) { byte result = RRuntime.LOGICAL_TRUE; try { RContext.getInstance().stateREnvVars.readEnvironFile(path); @@ -59,12 +62,4 @@ public abstract class ReadREnviron extends RBuiltinNode { return result; } - @Fallback - protected Object doReadEnviron(@SuppressWarnings("unused") Object vec) { - throw RError.error(this, RError.Message.ARGUMENT_MUST_BE_STRING, "x"); - } - - protected static boolean lengthOneCVector(RAbstractStringVector vec) { - return vec.getLength() == 1; - } } 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 63d70486b2bf75f7fd5b293fdf39bd0454bed25d..41f4eb9edbf28b16507ff62062abc6b9f5758287 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 @@ -27,6 +27,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.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.ConsoleHandler; @@ -35,6 +36,12 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "readline", kind = INTERNAL, parameterNames = "prompt", behavior = IO) public abstract class Readline extends RBuiltinNode { + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("prompt").asStringVector().findFirst(""); + } + @Specialization @TruffleBoundary protected String readline(RAbstractStringVector prompt) { 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 03395b1cca29c625d320395c1cac8ada93948329..0eeca3ebde014c43f4bbca7a83b788c7360614ba 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 @@ -22,14 +22,14 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; -import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.RExternalPtr; import com.oracle.truffle.r.runtime.data.RFunction; @@ -38,31 +38,27 @@ 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 { + @Override + protected void createCasts(CastBuilder casts) { + 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()); + } + @Specialization - protected RNull doRegFinalizer(RExternalPtr ext, RFunction fun, byte onexit) { + protected RNull doRegFinalizer(RExternalPtr ext, RFunction fun, boolean onexit) { return doRegFinalizerEither(ext, fun, onexit); } @Specialization - protected RNull doRegFinalizer(REnvironment env, RFunction fun, byte onexit) { + protected RNull doRegFinalizer(REnvironment env, RFunction fun, boolean onexit) { return doRegFinalizerEither(env, fun, onexit); } @SuppressWarnings("unused") - private RNull doRegFinalizerEither(Object env, RFunction fun, byte onexit) { - if (onexit == RRuntime.LOGICAL_NA) { - throw RError.error(this, RError.Message.REG_FINALIZER_THIRD); - } + private static RNull doRegFinalizerEither(Object env, RFunction fun, boolean onexit) { // TODO the actual work return RNull.instance; } - @SuppressWarnings("unused") - @Fallback - protected RNull doRegFinalizer(Object env, Object fun, byte onexit) { - if (fun instanceof RFunction) { - throw RError.error(this, RError.Message.REG_FINALIZER_FIRST); - } - throw RError.error(this, RError.Message.REG_FINALIZER_SECOND); - } } 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 12b25af55ac9e6b46c1311898a4f3e526d8bc076..87d600ab8713a6943f95fddd877addc949e7960f 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 @@ -22,15 +22,23 @@ */ 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.gte; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.intNA; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size; 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 java.util.Arrays; +import java.util.function.Function; +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.InitAttributesNode; +import com.oracle.truffle.r.nodes.attributes.PutAttributeNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; @@ -40,6 +48,7 @@ import com.oracle.truffle.r.runtime.data.RAttributeProfiles; 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.RTypedValue; 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; @@ -81,11 +90,19 @@ public abstract class Repeat extends RBuiltinNode { return new Object[]{RMissing.instance, 1, RRuntime.INT_NA, 1}; } + private String argType(Object arg) { + return ((RTypedValue) arg).getRType().getName(); + } + @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1); - casts.firstIntegerWithWarning(2, RRuntime.INT_NA, "length.out"); - casts.toInteger(3); + Function<Object, Object> argType = this::argType; + casts.arg("x").mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE, argType); + 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) { @@ -98,7 +115,12 @@ public abstract class Repeat extends RBuiltinNode { @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 length = lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut)) ? lengthOut : times.getDataAt(0); + 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))); @@ -128,46 +150,51 @@ public abstract class Repeat extends RBuiltinNode { } @Specialization(guards = {"each > 1", "hasNames(x)"}) - protected RAbstractVector repEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each) { + protected RAbstractVector repEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each, + @Cached("create()") InitAttributesNode initAttributes, + @Cached("createNames()") PutAttributeNode putNames) { if (times.getLength() > 1) { errorBranch.enter(); throw invalidTimes(); } RAbstractVector input = handleEach(x, each); RStringVector names = (RStringVector) handleEach(x.getNames(attrProfiles), each); + RVector<?> r; if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) { names = (RStringVector) handleLengthOut(names, lengthOut, false); - RVector r = handleLengthOut(input, lengthOut, false); - r.setNames(names); - return r; + r = handleLengthOut(input, lengthOut, false); } else { names = (RStringVector) handleTimes(names, times, false); - RVector r = handleTimes(input, times, false); - r.setNames(names); - return r; + r = handleTimes(input, times, false); } + putNames.execute(initAttributes.execute(r), names); + r.setInternalNames(names); + return r; } @Specialization(guards = {"each <= 1", "hasNames(x)"}) - protected RAbstractVector repNoEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each) { + protected RAbstractVector repNoEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each, + @Cached("create()") InitAttributesNode initAttributes, + @Cached("createNames()") PutAttributeNode putNames) { + RStringVector names; + RVector<?> r; if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) { - RStringVector names = (RStringVector) handleLengthOut(x.getNames(attrProfiles), lengthOut, true); - RVector r = handleLengthOut(x, lengthOut, true); - r.setNames(names); - return r; + names = (RStringVector) handleLengthOut(x.getNames(attrProfiles), lengthOut, true); + r = handleLengthOut(x, lengthOut, true); } else { - RStringVector names = (RStringVector) handleTimes(x.getNames(attrProfiles), times, true); - RVector r = handleTimes(x, times, true); - r.setNames(names); - return r; + names = (RStringVector) handleTimes(x.getNames(attrProfiles), times, true); + r = handleTimes(x, times, true); } + putNames.execute(initAttributes.execute(r), names); + r.setInternalNames(names); + 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()); + 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); @@ -179,9 +206,9 @@ public abstract class Repeat extends RBuiltinNode { /** * Extend or truncate the vector to a specified length. */ - private static RVector handleLengthOut(RAbstractVector x, int lengthOut, boolean copyIfSameSize) { + private static RVector<?> handleLengthOut(RAbstractVector x, int lengthOut, boolean copyIfSameSize) { if (x.getLength() == lengthOut) { - return (RVector) (copyIfSameSize ? x.copy() : x); + return (RVector<?>) (copyIfSameSize ? x.copy() : x); } return x.copyResized(lengthOut, false); } @@ -189,12 +216,16 @@ public abstract class Repeat extends RBuiltinNode { /** * Replicate the vector a given number of times. */ - private RVector handleTimes(RAbstractVector x, RAbstractIntVector times, boolean copyIfSameSize) { + 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(); + } if (replicateOnce.profile(howManyTimes == 1)) { - return (RVector) (copyIfSameSize ? x.copy() : x); + return (RVector<?>) (copyIfSameSize ? x.copy() : x); } else { return x.copyResized(x.getLength() * howManyTimes, false); } @@ -207,10 +238,15 @@ public abstract class Repeat extends RBuiltinNode { // iterate once over the times vector to determine result vector size int resultLength = 0; for (int i = 0; i < times.getLength(); i++) { - resultLength += times.getDataAt(i); + int t = times.getDataAt(i); + if (t < 0) { + errorBranch.enter(); + throw invalidTimes(); + } + resultLength += t; } // create and populate result vector - RVector r = x.createEmptySameType(resultLength, x.isComplete()); + 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) { 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 8515c9e92f97f8d0774f9f5ba2062522ec66dce0..5e6dd9e0c0312c66a0d24fbafe8fdc8d8b8f78ae 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 @@ -22,9 +22,11 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; +import java.util.function.Function; import java.util.function.IntFunction; import com.oracle.truffle.api.dsl.Specialization; @@ -41,6 +43,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.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; @@ -54,9 +57,16 @@ public abstract class RepeatInternal extends RBuiltinNode { private final ConditionProfile timesOneProfile = ConditionProfile.createBinaryProfile(); private final BranchProfile errorProfile = BranchProfile.create(); + private String argType(Object arg) { + return ((RTypedValue) arg).getRType().getName(); + } + @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1); + Function<Object, Object> argType = this::argType; + casts.arg("x").mustBe(abstractVectorValue(), RError.SHOW_CALLER2, RError.Message.ATTEMPT_TO_REPLICATE, argType); + 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"); } @FunctionalInterface @@ -76,6 +86,10 @@ public abstract class RepeatInternal extends RBuiltinNode { int valueLength = value.getLength(); if (timesOneProfile.profile(timesLength == 1)) { int timesValue = times.getDataAt(0); + if (timesValue < 0) { + errorProfile.enter(); + RError.error(this, RError.Message.INVALID_VALUE, "times"); + } int count = timesValue * valueLength; result = arrayConstructor.apply(count); int pos = 0; 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 9c4dc2ac4c8f163dfe80726d21008aa929a3003d..b13873f33ed598395c438a3c4364228d171d8edf 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 @@ -11,6 +11,9 @@ 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.notIntNA; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -19,6 +22,7 @@ import java.util.Arrays; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -40,7 +44,9 @@ public abstract class RepeatLength extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1); + casts.arg("x").mustBe(abstractVectorValue(), RError.SHOW_CALLER, 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()); } @Specialization 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 9005d96018a4e211fafd22acff0b1c4ad1985661..74eb30e05f18afe578d50382ab41fa390c7b1e91 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 @@ -22,6 +22,13 @@ */ 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; 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.INTERNAL; @@ -32,6 +39,7 @@ 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.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RError; @@ -43,15 +51,26 @@ 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; +/** + * 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 { private final BranchProfile invalidateProfile = BranchProfile.create(); + @Override + protected void createCasts(CastBuilder casts) { + 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, byte inherits) { + protected Object rm(VirtualFrame frame, String name, RMissing envir, boolean inherits) { removeFromFrame(frame, name); return RNull.instance; } @@ -59,7 +78,7 @@ public abstract class Rm extends RBuiltinNode { @Specialization @TruffleBoundary @SuppressWarnings("unused") - protected Object rm(RAbstractStringVector list, REnvironment envir, byte inherits) { + protected Object rm(RAbstractStringVector list, REnvironment envir, boolean inherits) { try { for (int i = 0; i < list.getLength(); i++) { if (envir == REnvironment.globalEnv()) { @@ -69,7 +88,7 @@ public abstract class Rm extends RBuiltinNode { } } } catch (PutException ex) { - throw RError.error(this, ex); + throw RError.error(SHOW_CALLER, ex); } return RNull.instance; } @@ -85,7 +104,7 @@ public abstract class Rm extends RBuiltinNode { } } if (fs == null) { - RError.warning(this, RError.Message.UNKNOWN_OBJECT, x); + RError.warning(SHOW_CALLER, 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 710cbe3459714bfc027d32b5dd835abc0695ddd7..9a9ead6cb2c3264d69a5e079290717534559e4ac 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 @@ -62,7 +62,8 @@ public abstract class Round extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1); + // TODO: this should also accept vectors: + casts.arg("digits").asIntegerVector().findFirst(); } @Specialization 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 7f03a651e9dd5bde1f756f1c6053939b21d08997..a24d5c11c2b0f209ac0ac614e69a5dd7f6f9a3ee 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 @@ -12,22 +12,29 @@ */ 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; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.RIntVector; -import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @RBuiltin(name = "row", kind = INTERNAL, parameterNames = {"dims"}, behavior = PURE) public abstract class Row extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("dims").defaultError(SHOW_CALLER, RError.Message.MATRIX_LIKE_REQUIRED, "row").mustBe(integerValue()).asIntegerVector().mustBe(size(2)); + } + @Specialization protected RIntVector col(RAbstractIntVector x) { int nrows = x.getDataAt(0); @@ -40,10 +47,4 @@ public abstract class Row extends RBuiltinNode { } return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR, new int[]{nrows, ncols}); } - - @Specialization - @TruffleBoundary - protected RIntVector col(@SuppressWarnings("unused") RNull x) { - throw RError.error(this, RError.Message.MATRIX_LIKE_REQUIRED, "row"); - } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowMeans.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowMeans.java index 5d97a4dac5811ed73dcbaa0fb2723ae96f6ad00a..dd72109980a9ce6bc16e31f436ce7f28737f10da 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowMeans.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowMeans.java @@ -10,191 +10,41 @@ */ 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.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.r.nodes.builtin.CastBuilder; -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.RDoubleVector; -import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; -import com.oracle.truffle.r.runtime.ops.na.NACheck; +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; // Implements .rowMeans @RBuiltin(name = "rowMeans", kind = INTERNAL, parameterNames = {"X", "m", "n", "na.rm"}, behavior = PURE) -public abstract class RowMeans extends RBuiltinNode { - - @Child private BinaryArithmetic add = BinaryArithmetic.ADD.create(); - private final NACheck na = NACheck.create(); - - @Override - protected void createCasts(CastBuilder casts) { - casts.arg("m").asIntegerVector().findFirst().notNA(); - - casts.arg("n").asIntegerVector().findFirst().notNA(); - - casts.arg("na.rm").asLogicalVector().findFirst().map(toBoolean()); - } - - @Specialization(guards = "!naRm") - @TruffleBoundary - protected RDoubleVector rowMeansNaRmFalse(RDoubleVector x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - double[] result = new double[rowNum]; - boolean isComplete = true; - na.enable(x); - nextRow: for (int i = 0; i < rowNum; i++) { - double sum = 0; - for (int c = 0; c < colNum; c++) { - double el = x.getDataAt(c * rowNum + i); - if (na.check(el)) { - result[i] = RRuntime.DOUBLE_NA; - continue nextRow; - } - if (Double.isNaN(el)) { - result[i] = Double.NaN; - isComplete = false; - continue nextRow; - } - sum = add.op(sum, el); - } - result[i] = sum / colNum; - } - return RDataFactory.createDoubleVector(result, na.neverSeenNA() && isComplete); - } - - @Specialization(guards = "naRm") - @TruffleBoundary - protected RDoubleVector rowMeansNaRmTrue(RDoubleVector x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - double[] result = new double[rowNum]; - boolean isComplete = true; - na.enable(x); - for (int i = 0; i < rowNum; i++) { - double sum = 0; - int nonNaNumCount = 0; - for (int c = 0; c < colNum; c++) { - double el = x.getDataAt(c * rowNum + i); - if (!na.check(el) && !Double.isNaN(el)) { - sum = add.op(sum, el); - nonNaNumCount++; - } - } - if (nonNaNumCount == 0) { - result[i] = Double.NaN; - isComplete = false; - } else { - result[i] = sum / nonNaNumCount; - } - } - return RDataFactory.createDoubleVector(result, isComplete); - } - - @Specialization(guards = "!naRm") - @TruffleBoundary - protected RDoubleVector rowMeansNaRmFalse(RLogicalVector x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - double[] result = new double[rowNum]; - na.enable(x); - nextRow: for (int i = 0; i < rowNum; i++) { - double sum = 0; - for (int c = 0; c < colNum; c++) { - byte el = x.getDataAt(c * rowNum + i); - if (na.check(el)) { - result[i] = RRuntime.DOUBLE_NA; - continue nextRow; - } - sum = add.op(sum, el); - } - result[i] = sum / colNum; - } - return RDataFactory.createDoubleVector(result, na.neverSeenNA()); +public abstract class RowMeans extends RowSumsBase { + @Specialization + protected RDoubleVector rowMeans(RAbstractDoubleVector x, int rowNum, int colNum, boolean naRm) { + return accumulateRows(x, rowNum, colNum, naRm, RowMeans::getMean, (v, nacheck, i) -> v.getDataAt(i)); } - @Specialization(guards = "naRm") - @TruffleBoundary - protected RDoubleVector rowMeansNaRmTrue(RLogicalVector x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - double[] result = new double[rowNum]; - boolean isComplete = true; - na.enable(x); - for (int i = 0; i < rowNum; i++) { - double sum = 0; - int nonNaNumCount = 0; - for (int c = 0; c < colNum; c++) { - byte el = x.getDataAt(c * rowNum + i); - if (!na.check(el)) { - sum = add.op(sum, el); - nonNaNumCount++; - } - } - if (nonNaNumCount == 0) { - result[i] = Double.NaN; - isComplete = false; - } else { - result[i] = sum / nonNaNumCount; - } - } - return RDataFactory.createDoubleVector(result, isComplete); + @Specialization + protected RDoubleVector rowMeans(RAbstractIntVector x, int rowNum, int colNum, boolean naRm) { + return accumulateRows(x, rowNum, colNum, naRm, RowMeans::getMean, (v, nacheck, i) -> nacheck.convertIntToDouble(v.getDataAt(i))); } - @Specialization(guards = "!naRm") - @TruffleBoundary - protected RDoubleVector rowMeansNaRmFalse(RIntVector x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - double[] result = new double[rowNum]; - na.enable(x); - nextRow: for (int i = 0; i < rowNum; i++) { - double sum = 0; - for (int c = 0; c < colNum; c++) { - int el = x.getDataAt(c * rowNum + i); - if (na.check(el)) { - result[i] = RRuntime.DOUBLE_NA; - continue nextRow; - } - sum = add.op(sum, el); - } - result[i] = sum / colNum; - } - return RDataFactory.createDoubleVector(result, na.neverSeenNA()); + @Specialization + protected RDoubleVector rowMeans(RAbstractLogicalVector x, int rowNum, int colNum, boolean naRm) { + return accumulateRows(x, rowNum, colNum, naRm, RowMeans::getMean, (v, nacheck, i) -> nacheck.convertLogicalToDouble(v.getDataAt(i))); } - @Specialization(guards = "naRm") - @TruffleBoundary - protected RDoubleVector rowMeansNaRmTrue(RIntVector x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) { - double[] result = new double[rowNum]; - boolean isComplete = true; - na.enable(x); - for (int i = 0; i < rowNum; i++) { - double sum = 0; - int nonNaNumCount = 0; - for (int c = 0; c < colNum; c++) { - int el = x.getDataAt(c * rowNum + i); - if (!na.check(el)) { - sum = add.op(sum, el); - nonNaNumCount++; - } - } - if (nonNaNumCount == 0) { - result[i] = Double.NaN; - isComplete = false; - } else { - result[i] = sum / nonNaNumCount; - } + private static double getMean(double sum, int notNACount) { + if (Double.isNaN(sum)) { + return sum; + } else if (notNACount == 0) { + return Double.NaN; + } else { + return sum / notNACount; } - return RDataFactory.createDoubleVector(result, isComplete); } - - @SuppressWarnings("unused") - @Specialization - protected RDoubleVector rowMeans(RAbstractStringVector x, int rowNum, int colNum, boolean naRm) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.X_NUMERIC); - } - } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSums.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSums.java index 3660bf75ee1d03e56c6beacf49d56d6b6da2f8a5..4fe2545e4c6436b4c6f9f347c7f78c672880f687 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSums.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSums.java @@ -13,122 +13,27 @@ 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.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.api.profiles.LoopConditionProfile; -import com.oracle.truffle.r.nodes.builtin.CastBuilder; -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.RDoubleVector; 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 com.oracle.truffle.r.runtime.ops.BinaryArithmetic; -import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "rowSums", kind = INTERNAL, parameterNames = {"X", "m", "n", "na.rm"}, behavior = PURE) -public abstract class RowSums extends RBuiltinNode { - - /* - * this builtin unrolls the innermost loop (calculating multiple sums at once) to optimize cache - * behavior. - */ - private static final int UNROLL = 8; - - @Child private BinaryArithmetic add = BinaryArithmetic.ADD.create(); - - private final NACheck na = NACheck.create(); - - private final ConditionProfile removeNA = ConditionProfile.createBinaryProfile(); - private final ConditionProfile remainderProfile = ConditionProfile.createBinaryProfile(); - private final LoopConditionProfile outerProfile = LoopConditionProfile.createCountingProfile(); - private final LoopConditionProfile innerProfile = LoopConditionProfile.createCountingProfile(); - - @Override - protected void createCasts(CastBuilder casts) { - casts.toInteger(1).toInteger(2); - } - - @FunctionalInterface - private interface GetFunction<T extends RAbstractVector> { - double get(T vector, NACheck na, int index); - } - - private <T extends RAbstractVector> RDoubleVector performSums(T x, int rowNum, int colNum, byte naRm, GetFunction<T> get) { - reportWork(x.getLength()); - double[] result = new double[rowNum]; - final boolean rna = removeNA.profile(naRm == RRuntime.LOGICAL_TRUE); - na.enable(x); - outerProfile.profileCounted(rowNum / 4); - innerProfile.profileCounted(colNum); - int i = 0; - // the unrolled loop cannot handle NA values - if (!na.isEnabled()) { - while (outerProfile.inject(i <= rowNum - UNROLL)) { - double[] sum = new double[UNROLL]; - int pos = i; - for (int c = 0; innerProfile.inject(c < colNum); c++) { - for (int unroll = 0; unroll < UNROLL; unroll++) { - sum[unroll] = add.op(sum[unroll], get.get(x, na, pos + unroll)); - } - pos += rowNum; - } - for (int unroll = 0; unroll < UNROLL; unroll++) { - result[i + unroll] = sum[unroll]; - } - i += UNROLL; - } - } - if (remainderProfile.profile(i < rowNum)) { - while (i < rowNum) { - double sum = 0; - int pos = i; - for (int c = 0; innerProfile.inject(c < colNum); c++) { - double el = get.get(x, na, pos); - pos += rowNum; - if (Double.isNaN(el)) { - // call check to make sure neverSeenNA is correct - na.check(el); - if (!rna) { - sum = el; - break; - } - } else { - sum = add.op(sum, el); - } - } - result[i] = sum; - i++; - } - } - return RDataFactory.createDoubleVector(result, na.neverSeenNA()); - } - - @Specialization - protected RDoubleVector rowSums(RAbstractDoubleVector x, int rowNum, int colNum, byte naRm) { - return performSums(x, rowNum, colNum, naRm, (v, nacheck, i) -> v.getDataAt(i)); - } - +public abstract class RowSums extends RowSumsBase { @Specialization - protected RDoubleVector rowSums(RAbstractIntVector x, int rowNum, int colNum, byte naRm) { - return performSums(x, rowNum, colNum, naRm, (v, nacheck, i) -> nacheck.convertIntToDouble(v.getDataAt(i))); + protected RDoubleVector rowSums(RAbstractDoubleVector x, int rowNum, int colNum, boolean naRm) { + return accumulateRows(x, rowNum, colNum, naRm, (sum, cnt) -> sum, (v, nacheck, i) -> v.getDataAt(i)); } @Specialization - protected RDoubleVector rowSums(RAbstractLogicalVector x, int rowNum, int colNum, byte naRm) { - return performSums(x, rowNum, colNum, naRm, (v, nacheck, i) -> nacheck.convertLogicalToDouble(v.getDataAt(i))); + protected RDoubleVector rowSums(RAbstractIntVector x, int rowNum, int colNum, boolean naRm) { + return accumulateRows(x, rowNum, colNum, naRm, (sum, cnt) -> sum, (v, nacheck, i) -> nacheck.convertIntToDouble(v.getDataAt(i))); } - @SuppressWarnings("unused") @Specialization - @TruffleBoundary - protected RDoubleVector rowSums(RAbstractStringVector x, int rowNum, int colNum, byte naRm) { - throw RError.error(this, RError.Message.X_NUMERIC); + protected RDoubleVector rowSums(RAbstractLogicalVector x, int rowNum, int colNum, boolean naRm) { + return accumulateRows(x, rowNum, colNum, naRm, (sum, cnt) -> sum, (v, nacheck, i) -> nacheck.convertLogicalToDouble(v.getDataAt(i))); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSumsBase.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSumsBase.java new file mode 100644 index 0000000000000000000000000000000000000000..288587ebf798d9140bf321c6d81c467f07df3fe6 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSumsBase.java @@ -0,0 +1,114 @@ +/* + * 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.builtin.base; + +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.LoopConditionProfile; +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.model.RAbstractVector; +import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; +import com.oracle.truffle.r.runtime.ops.na.NACheck; + +/** + * Implements a skeleton of an algorithm that traverses rows and accumulates their values. + */ +public abstract class RowSumsBase extends ColSumsBase { + + /* + * this builtin unrolls the innermost loop (calculating multiple sums at once) to optimize cache + * behavior. + */ + private static final int UNROLL = 8; + + @Child private BinaryArithmetic add = BinaryArithmetic.ADD.create(); + + private final ConditionProfile remainderProfile = ConditionProfile.createBinaryProfile(); + private final LoopConditionProfile outerProfile = LoopConditionProfile.createCountingProfile(); + private final LoopConditionProfile innerProfile = LoopConditionProfile.createCountingProfile(); + + @FunctionalInterface + protected interface GetFunction<T extends RAbstractVector> { + double get(T vector, NACheck na, int index); + } + + @FunctionalInterface + protected interface FinalTransform { + double get(double sum, int notNACount); + } + + protected final <T extends RAbstractVector> RDoubleVector accumulateRows(T x, int rowNum, int colNum, boolean naRm, FinalTransform finalTransform, RowSumsBase.GetFunction<T> get) { + reportWork(x.getLength()); + double[] result = new double[rowNum]; + na.enable(x); + outerProfile.profileCounted(rowNum / 4); + innerProfile.profileCounted(colNum); + int i = 0; + // the unrolled loop cannot handle NA values + if (!na.isEnabled()) { + while (outerProfile.inject(i <= rowNum - UNROLL)) { + double[] sum = new double[UNROLL]; + int pos = i; + for (int c = 0; innerProfile.inject(c < colNum); c++) { + for (int unroll = 0; unroll < UNROLL; unroll++) { + sum[unroll] = add.op(sum[unroll], get.get(x, na, pos + unroll)); + } + pos += rowNum; + } + for (int unroll = 0; unroll < UNROLL; unroll++) { + result[i + unroll] = finalTransform.get(sum[unroll], colNum); + } + i += UNROLL; + } + } + if (remainderProfile.profile(i < rowNum)) { + while (i < rowNum) { + double sum = 0; + int pos = i; + int notNACount = 0; + for (int c = 0; innerProfile.inject(c < colNum); c++) { + double el = get.get(x, na, pos); + pos += rowNum; + if (na.check(el)) { + if (!naRm) { + sum = RRuntime.DOUBLE_NA; + break; + } + } else if (Double.isNaN(el)) { + if (!naRm) { + sum = Double.NaN; + break; + } + } else { + sum = add.op(sum, el); + notNACount++; + } + } + result[i] = finalTransform.get(sum, notNACount); + i++; + } + } + return RDataFactory.createDoubleVector(result, na.neverSeenNA()); + } +} 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 b0e65daa31828bff7c0c7e0a1889f3f6aeaf7feb..207312d8a64a1ec44f1c22307794fdccb5b51052 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 @@ -30,11 +30,12 @@ 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.RList; import com.oracle.truffle.r.runtime.data.RNull; 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.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -83,12 +84,12 @@ public class RowsumFunctions { int offsetg = 0; boolean isInt = xv instanceof RIntVector; - RVector result; + RVector<?> result; na.enable(xv); boolean complete = xv.isComplete(); if (typeProfile.profile(isInt)) { - RIntVector xi = (RIntVector) xv; + RAbstractIntVector xi = (RAbstractIntVector) xv; int[] ansi = new int[ng * p]; for (int i = 0; i < p; i++) { for (int j = 0; j < n; j++) { @@ -117,7 +118,7 @@ public class RowsumFunctions { } result = RDataFactory.createIntVector(ansi, complete, new int[]{ng, p}); } else { - RDoubleVector xd = (RDoubleVector) xv; + RAbstractDoubleVector xd = (RAbstractDoubleVector) xv; double[] ansd = new double[ng * p]; for (int i = 0; i < p; i++) { for (int j = 0; j < n; j++) { 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 5dfe6d00ea2500af2aa60793b1e393170a48f2b8..682bbc28bcc7795c9afdcabc80e33ce16383d444 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 @@ -14,6 +14,24 @@ 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.chain; +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.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.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.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; +import static com.oracle.truffle.r.runtime.RError.Message.VECTOR_SIZE_TOO_LARGE; import static com.oracle.truffle.r.runtime.builtins.RBehavior.MODIFIES_STATE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -30,7 +48,6 @@ 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.RAbstractVector; import com.oracle.truffle.r.runtime.rng.RRNG; @RBuiltin(name = "sample", kind = INTERNAL, parameterNames = {"x", "size", "replace", "prob"}, behavior = MODIFIES_STATE) @@ -39,44 +56,61 @@ public abstract class Sample extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(0); - casts.toInteger(1); - casts.toLogical(2); - casts.toDouble(3); + // @formatter:off + 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").allowNull().asDoubleVector(); + // @formatter:on } - @Specialization(guards = "invalidFirstArgument(x, size)") - @SuppressWarnings("unused") - protected RIntVector doSampleInvalidFirstArg(final int x, final int size, final byte isRepeatable, final RDoubleVector prob) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_FIRST_ARGUMENT); + // Validation that correlates two or more argument values (note: positiveness of prob is checked + // in fixupProbability) + + protected static boolean largerPopulation(final int x, final int size, final boolean isRepeatable) { + return !isRepeatable && size > x; + } + + protected static boolean invalidProb(final int x, final RDoubleVector prob) { + return prob.getLength() != x; } @Specialization(guards = "invalidProb(x, prob)") @SuppressWarnings("unused") - protected RIntVector doSampleInvalidProb(final int x, final int size, final byte isRepeatable, final RDoubleVector prob) { + protected RIntVector doSampleInvalidProb(final int x, final int size, final boolean isRepeatable, final RDoubleVector prob) { CompilerDirectives.transferToInterpreter(); throw RError.error(this, RError.Message.INCORRECT_NUM_PROB); } @Specialization(guards = "largerPopulation(x, size, isRepeatable)") @SuppressWarnings("unused") - protected RIntVector doSampleLargerPopulation(final int x, final int size, final byte isRepeatable, final RDoubleVector prob) { + protected RIntVector doSampleLargerPopulation(final int x, final int size, final boolean isRepeatable, final RDoubleVector prob) { CompilerDirectives.transferToInterpreter(); throw RError.error(this, RError.Message.SAMPLE_LARGER_THAN_POPULATION); } - @Specialization(guards = "invalidSizeArgument(size)") @SuppressWarnings("unused") - protected RIntVector doSampleInvalidSize(final int x, final int size, final byte isRepeatable, final RDoubleVector prob) { + @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.INVALID_ARGUMENT, RRuntime.intToString(size)); - + throw RError.error(this, RError.Message.INCORRECT_NUM_PROB); } - @Specialization(guards = {"!invalidFirstArgument(x, size)", "!invalidProb(x, prob)", "!largerPopulation(x, size, isRepeatable)", "!invalidSizeArgument(size)", "withReplacement(isRepeatable)"}) + // Actual specializations: + + @Specialization(guards = {"!invalidProb(x, prob)", "!largerPopulation(x, size, isRepeatable)", "isRepeatable"}) @TruffleBoundary - protected RIntVector doSampleWithReplacement(final int x, final int size, final byte isRepeatable, final RDoubleVector prob) { + protected RIntVector doSampleWithReplacement(final int x, final int size, final boolean isRepeatable, final RDoubleVector prob) { // The following code is transcribed from GNU R src/main/random.c lines 493-501 in // function do_sample. double[] probArray = prob.getDataCopy(); @@ -95,44 +129,23 @@ public abstract class Sample extends RBuiltinNode { } } - @Specialization(guards = {"!invalidFirstArgument(x, size)", "!invalidProb(x, prob)", "!largerPopulation(x, size, isRepeatable)", "!invalidSizeArgument(size)", "!withReplacement(isRepeatable)"}) + @Specialization(guards = {"!invalidProb(x, prob)", "!largerPopulation(x, size, isRepeatable)", "!isRepeatable"}) @TruffleBoundary - protected RIntVector doSampleNoReplacement(final int x, final int size, final byte isRepeatable, final RDoubleVector prob) { + protected RIntVector doSampleNoReplacement(final int x, final int size, final boolean isRepeatable, final RDoubleVector prob) { double[] probArray = prob.getDataCopy(); fixupProbability(probArray, x, size, isRepeatable); return RDataFactory.createIntVector(probSampleWithoutReplace(x, probArray, size), RDataFactory.COMPLETE_VECTOR); } - @SuppressWarnings("unused") - @Specialization(guards = "invalidFirstArgumentNullProb(x, size)") - protected RIntVector doSampleInvalidFirstArgument(final int x, final int size, final byte isRepeatable, final RNull prob) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_FIRST_ARGUMENT); - } - - @SuppressWarnings("unused") - @Specialization(guards = "invalidSizeArgument(size)") - protected RIntVector doSampleInvalidSizeArgument(final int x, final int size, final byte isRepeatable, final RNull prob) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, RRuntime.intToString(size)); - } - - @SuppressWarnings("unused") - @Specialization(guards = "largerPopulation(x, size, isRepeatable)") - protected RIntVector doSampleInvalidLargerPopulation(final int x, final int size, final byte isRepeatable, final RNull prob) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INCORRECT_NUM_PROB); - } - - @Specialization(guards = {"!invalidFirstArgumentNullProb(x, size)", "!invalidSizeArgument(size)", "!largerPopulation(x, size, isRepeatable)"}) + @Specialization(guards = {"!largerPopulation(x, size, isRepeatable)"}) @TruffleBoundary - protected RIntVector doSample(final int x, final int size, final byte isRepeatable, @SuppressWarnings("unused") final RNull prob) { + protected RIntVector doSample(final int x, final int size, final boolean isRepeatable, @SuppressWarnings("unused") final RNull prob) { // TODO:Add support of long integers. // The following code is transcribed from GNU R src/main/random.c lines 533-545 in // function do_sample. int[] result = new int[size]; /* avoid allocation for a single sample */ - if (sampleSizeProfile.profile(isRepeatable == RRuntime.LOGICAL_TRUE || size < 2)) { + if (sampleSizeProfile.profile(isRepeatable || size < 2)) { for (int i = 0; i < size; i++) { result[i] = (int) (x * RRNG.unifRand() + 1); } @@ -151,15 +164,8 @@ public abstract class Sample extends RBuiltinNode { return RDataFactory.createIntVector(result, true); } - @SuppressWarnings("unused") - @Specialization(guards = "invalidIsRepeatable(isRepeatable)") - protected RIntVector doSampleInvalidIsRepeatable(int x, int size, byte isRepeatable, RDoubleVector prob) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, RRuntime.logicalToString(isRepeatable)); - } - @TruffleBoundary - private void fixupProbability(double[] probArray, int x, int size, byte isRepeatable) { + private void fixupProbability(double[] probArray, int x, int size, boolean isRepeatable) { // The following code is transcribed from GNU R src/main/random.c lines 429-449 int nonZeroProbCount = 0; double probSum = 0; @@ -175,7 +181,7 @@ public abstract class Sample extends RBuiltinNode { nonZeroProbCount++; } } - if (nonZeroProbCount == 0 || (isRepeatable == RRuntime.LOGICAL_FALSE && size > nonZeroProbCount)) { + if (nonZeroProbCount == 0 || (!isRepeatable && size > nonZeroProbCount)) { throw RError.error(this, RError.Message.TOO_FEW_POSITIVE_PROBABILITY); } for (int i = 0; i < x; i++) { @@ -183,34 +189,6 @@ public abstract class Sample extends RBuiltinNode { } } - protected static boolean invalidFirstArgumentNullProb(final int x, final int size) { - return !RRuntime.isFinite(x) || x < 0 || x > 4.5e15 || (size > 0 && x == 0); - } - - protected static boolean invalidSizeArgument(int size) { - return RRuntime.isNA(size) || size < 0; - } - - protected static boolean largerPopulation(final int x, final int size, final byte isRepeatable) { - return isRepeatable == RRuntime.LOGICAL_FALSE && size > x; - } - - protected static boolean invalidFirstArgument(final int x, final int size) { - return RRuntime.isNA(x) || x < 0 || (size > 0 && x == 0); - } - - protected static boolean invalidProb(final int x, final RAbstractVector prob) { - return prob.getLength() != x; - } - - protected static boolean withReplacement(final byte isRepeatable) { - return isRepeatable == RRuntime.LOGICAL_TRUE; - } - - protected static boolean invalidIsRepeatable(final byte isRepeatable) { - return RRuntime.isNA(isRepeatable); - } - @TruffleBoundary private int[] probSampleReplace(int n, double[] probArray, int resultSize) { // The following code is transcribed from GNU R src/main/random.c lines 309-335 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 304af5f57e8333b6ea11b5a962f98d9607d0ca77..28ed2c67637d61df73ae84d1d09a32aa9b3d1c45 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 @@ -12,7 +12,15 @@ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; +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.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.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.builtins.RBehavior.IO; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -30,7 +38,6 @@ 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.builtins.RBehavior; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.conn.StdConnections; @@ -45,14 +52,11 @@ 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.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.ops.na.NACheck; -import com.sun.org.apache.bcel.internal.generic.INSTANCEOF; -@SuppressWarnings("unused") @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 { @@ -74,6 +78,7 @@ public abstract class Scan extends RBuiltinNode { return ((RAbstractVector) castVector.execute(value)).materialize(); } + @SuppressWarnings("unused") private static class LocalData { RAbstractStringVector naStrings = null; boolean quiet = false; @@ -103,12 +108,12 @@ public abstract class Scan extends RBuiltinNode { casts.arg("nmax").asIntegerVector().findFirst(0).notNA(0).mapIf(lt(0), constant(0)); - casts.arg("sep").mustBe(nullValue().or(stringValue())).asStringVector().findFirst("").mustBe(lengthLte(1), RError.Message.MUST_BE_ONE_BYTE, "'sep' value"); + casts.arg("sep").allowNull().mustBe(stringValue()).asStringVector().findFirst("").mustBe(lengthLte(1), RError.Message.MUST_BE_ONE_BYTE, "'sep' value"); - casts.arg("dec").defaultError(RError.Message.INVALID_DECIMAL_SEP).mustBe(nullValue().or(stringValue())).asStringVector().findFirst(".").mustBe(length(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), + RError.Message.MUST_BE_ONE_BYTE, "'sep' value"); - casts.arg("quote").defaultError(RError.Message.INVALID_QUOTE_SYMBOL).mapIf(nullValue(), constant("")).mustBe(stringValue()).asStringVector().findFirst(""); + 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)); @@ -139,6 +144,7 @@ public abstract class Scan extends RBuiltinNode { } @Specialization + @TruffleBoundary protected Object doScan(RConnection file, RAbstractVector what, int nmax, String sep, String dec, String quotes, int nskip, int nlines, RAbstractStringVector naStringsVec, boolean flush, boolean fill, RAbstractLogicalVector stripVec, boolean quiet, boolean blSkip, boolean multiLine, int commentChar, boolean escapes, @@ -181,7 +187,6 @@ public abstract class Scan extends RBuiltinNode { // TODO: quite a few more things happen in GNU R around connections data.con = file; - Object result = RNull.instance; data.save = 0; try (RConnection openConn = data.con.forceOpen("r")) { @@ -199,14 +204,6 @@ public abstract class Scan extends RBuiltinNode { } } - private static int firstElementOrNA(RAbstractIntVector nmaxVec) { - return nmaxVec.getLength() == 0 ? RRuntime.INT_NA : nmaxVec.getDataAt(0); - } - - private static byte firstElementOrNA(RAbstractLogicalVector flushVec) { - return flushVec.getLength() == 0 ? RRuntime.LOGICAL_NA : flushVec.getDataAt(0); - } - private static int getFirstQuoteInd(String str, char sepChar) { int quoteInd = str.indexOf(sepChar); if (quoteInd >= 0) { @@ -315,12 +312,14 @@ public abstract class Scan extends RBuiltinNode { private void fillEmpty(int from, int to, int records, RList list, LocalData data) { for (int i = from; i < to; i++) { - RVector vec = (RVector) list.getDataAt(i); + RVector<?> vec = (RVector<?>) list.getDataAt(i); vec.updateDataAtAsObject(records, extractItem(vec, "", data), naCheck); } } - private RVector scanFrame(RList what, int maxRecords, int maxLines, boolean flush, boolean fill, boolean stripWhite, boolean blSkip, boolean multiLine, LocalData data) throws IOException { + private RVector<?> scanFrame(RList what, int maxRecords, int maxLines, boolean flush, boolean fill, @SuppressWarnings("unused") boolean stripWhite, boolean blSkip, boolean multiLine, + LocalData data) + throws IOException { int nc = what.getLength(); if (nc == 0) { @@ -346,7 +345,7 @@ public abstract class Scan extends RBuiltinNode { } @TruffleBoundary - private RVector scanFrameInternal(int maxRecords, int maxLines, boolean flush, boolean fill, boolean blSkip, boolean multiLine, LocalData data, int nc, int initialBlockSize, RList list) + private RVector<?> scanFrameInternal(int maxRecords, int maxLines, boolean flush, boolean fill, boolean blSkip, boolean multiLine, LocalData data, int nc, int initialBlockSize, RList list) throws IOException { int blockSize = initialBlockSize; int n = 0; @@ -387,13 +386,13 @@ public abstract class Scan extends RBuiltinNode { // enlarge the vector blockSize = blockSize * 2; for (int j = 0; j < nc; j++) { - RVector vec = (RVector) list.getDataAt(j); + RVector<?> vec = (RVector<?>) list.getDataAt(j); vec = vec.copyResized(blockSize, false); list.updateDataAt(j, vec, null); } } - RVector vec = (RVector) list.getDataAt(n); + RVector<?> vec = (RVector<?>) list.getDataAt(n); vec.updateDataAtAsObject(records, item, naCheck); n++; if (n == nc) { @@ -432,7 +431,7 @@ public abstract class Scan extends RBuiltinNode { } // trim vectors if necessary for (int i = 0; i < nc; i++) { - RVector vec = (RVector) list.getDataAt(i); + RVector<?> vec = (RVector<?>) list.getDataAt(i); if (vec.getLength() > records) { list.updateDataAt(i, vec.copyResized(records, false), null); } @@ -442,9 +441,10 @@ public abstract class Scan extends RBuiltinNode { } @TruffleBoundary - private RVector scanVector(RAbstractVector what, int maxItems, int maxLines, boolean flush, boolean stripWhite, boolean blSkip, LocalData data) throws IOException { + private RVector<?> scanVector(RAbstractVector what, int maxItems, int maxLines, @SuppressWarnings("unused") boolean flush, @SuppressWarnings("unused") boolean stripWhite, boolean blSkip, + LocalData data) throws IOException { int blockSize = maxItems > 0 ? maxItems : SCAN_BLOCKSIZE; - RVector vec = what.createEmptySameType(blockSize, RDataFactory.COMPLETE_VECTOR); + RVector<?> vec = what.createEmptySameType(blockSize, RDataFactory.COMPLETE_VECTOR); naCheck.enable(true); int n = 0; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Seq.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Seq.java index 4d9963247acf9d1ae12a76b1155dd7cf855a65d3..6d9446605d383ce049dbab8a4697312ec6760e0d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Seq.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Seq.java @@ -26,9 +26,11 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.SUBSTITUTE; 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.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; @@ -53,8 +55,13 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; // below) @SuppressWarnings("unused") public abstract class Seq extends RBuiltinNode { + + // TODO: warnings for non-scalar values of stride are quite weird (for now we simply assume that + // stride is of length one) + private final ConditionProfile lengthProfile1 = ConditionProfile.createBinaryProfile(); private final ConditionProfile lengthProfile2 = ConditionProfile.createBinaryProfile(); + private final ConditionProfile topLengthProfile = ConditionProfile.createBinaryProfile(); private final BranchProfile error = BranchProfile.create(); @Child private Seq seqRecursive; @@ -112,7 +119,7 @@ public abstract class Seq extends RBuiltinNode { private void validateParams(double start, double to) { validateParam(start, "from"); - validateParam(start, "to"); + validateParam(to, "to"); } private void validateParams(RAbstractDoubleVector start, RAbstractDoubleVector to) { @@ -124,15 +131,6 @@ public abstract class Seq extends RBuiltinNode { } } - private void validateParams(RAbstractLogicalVector start, RAbstractLogicalVector to) { - if (start != null) { - validateParam(RRuntime.logical2int(start.getDataAt(0)), "from"); - } - if (to != null) { - validateParam(RRuntime.logical2int(start.getDataAt(0)), "to"); - } - } - private RDoubleVector getVectorWithComputedStride(double start, double to, double lengthOut, boolean ascending) { validateParams(start, to); int length = (int) Math.ceil(lengthOut); @@ -183,322 +181,368 @@ public abstract class Seq extends RBuiltinNode { return RDataFactory.createIntSequence(1, 1, start.getLength()); } - // int vector start, missing to + @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "zero(start, to)"}) + protected int seqZero(RAbstractIntVector start, RAbstractIntVector to, Object stride, RMissing lengthOut, RMissing alongWith) { + return 0; + } - @Specialization(guards = "!startEmpty(start)") - protected RIntSequence seqFromOneArg(RAbstractIntVector start, RMissing to, RMissing stride, RMissing lengthOut, RMissing alongWith) { - validateParam(start.getDataAt(0), "to"); - // GNU R really does that (take the length of start to create a sequence) - return RDataFactory.createIntSequence(1, 1, start.getLength()); + @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "zero(start, to)"}) + protected int seqZero(RAbstractDoubleVector start, RAbstractIntVector to, Object stride, RMissing lengthOut, RMissing alongWith) { + return 0; } - @Specialization(guards = "startEmpty(start)") - protected RIntVector seqFromOneArgEmpty(RAbstractIntVector start, RMissing to, RMissing stride, RMissing lengthOut, RMissing alongWith) { - return RDataFactory.createEmptyIntVector(); + @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "zero(start, to)"}) + protected int seqZero(RAbstractIntVector start, RAbstractDoubleVector to, Object stride, RMissing lengthOut, RMissing alongWith) { + return 0; } - @Specialization(guards = {"startLengthOne(start)", "!lengthZero(lengthOut)"}) - protected RDoubleSequence seq(RAbstractIntVector start, RMissing to, RMissing stride, int lengthOut, RMissing alongWith) { - validateParam(start.getDataAt(0), "from"); - return RDataFactory.createDoubleSequence(RRuntime.int2double(start.getDataAt(0)), 1, lengthOut); + @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "zero(start, to)"}) + protected int seqZero(RAbstractDoubleVector start, RAbstractDoubleVector to, Object stride, RMissing lengthOut, RMissing alongWith) { + return 0; } - @Specialization(guards = {"startLengthOne(start)", "!lengthZero(lengthOut)"}) - protected RDoubleSequence seq(RAbstractIntVector start, RMissing to, RMissing stride, double lengthOut, RMissing alongWith) { - validateParam(start.getDataAt(0), "from"); - return RDataFactory.createDoubleSequence(RRuntime.int2double(start.getDataAt(0)), 1, (int) Math.ceil(lengthOut)); + // int vector start, missing to + + @Specialization + protected RAbstractIntVector seqFromOneArg(RAbstractIntVector start, RMissing to, RMissing stride, RMissing lengthOut, RMissing alongWith) { + if (topLengthProfile.profile(start.getLength() == 0)) { + return RDataFactory.createEmptyIntVector(); + } else { + validateParam(start.getDataAt(0), "to"); + // GNU R really does that (take the length of start to create a sequence) + return RDataFactory.createIntSequence(1, 1, start.getLength()); + } } - @Specialization(guards = {"startLengthOne(start)", "lengthZero(lengthOut)"}) - protected RIntVector seqLengthZero(RAbstractIntVector start, RMissing to, RMissing stride, int lengthOut, RMissing alongWith) { + @Specialization + protected RAbstractVector seq(RAbstractIntVector start, RMissing to, RMissing stride, int lengthOut, RMissing alongWith) { + startLengthOne(start); validateParam(start.getDataAt(0), "from"); - return RDataFactory.createEmptyIntVector(); + if (topLengthProfile.profile(lengthOut == 0)) { + return RDataFactory.createEmptyIntVector(); + } else { + return RDataFactory.createDoubleSequence(RRuntime.int2double(start.getDataAt(0)), 1, lengthOut); + } } - @Specialization(guards = {"startLengthOne(start)", "lengthZero(lengthOut)"}) - protected RIntVector seqLengthZero(RAbstractIntVector start, RMissing to, RMissing stride, double lengthOut, RMissing alongWith) { + @Specialization + protected RAbstractVector seq(RAbstractIntVector start, RMissing to, RMissing stride, double lengthOut, RMissing alongWith) { + startLengthOne(start); validateParam(start.getDataAt(0), "from"); - return RDataFactory.createEmptyIntVector(); + if (topLengthProfile.profile(lengthOut == 0)) { + return RDataFactory.createEmptyIntVector(); + } else { + return RDataFactory.createDoubleSequence(RRuntime.int2double(start.getDataAt(0)), 1, (int) Math.ceil(lengthOut)); + } } // int vector start, int vector to - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "zero(start, to)"}) - protected int seqZero(RAbstractIntVector start, RAbstractIntVector to, Object stride, RMissing lengthOut, RMissing alongWith) { - return 0; - } - - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!zero(start, to)"}) - protected RIntSequence seq(RAbstractIntVector start, RAbstractIntVector to, RMissing stride, RMissing lengthOut, RMissing alongWith) { + @Specialization + protected Object seq(RAbstractIntVector start, RAbstractIntVector to, RMissing stride, RMissing lengthOut, RMissing alongWith) { + startLengthOne(start); + toLengthOne(to); validateParams(start, to); - return RDataFactory.createIntSequence(start.getDataAt(0), ascending(start, to) ? 1 : -1, Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1); + if (topLengthProfile.profile(zero(start, to))) { + return 0; + } else { + return RDataFactory.createIntSequence(start.getDataAt(0), ascending(start, to) ? 1 : -1, Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1); + } } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!zero(start, to)"}) - protected RIntSequence seq(RAbstractIntVector start, RAbstractIntVector to, int stride, RMissing lengthOut, RMissing alongWith) { + @Specialization + protected Object seq(RAbstractIntVector start, RAbstractIntVector to, RAbstractIntVector stride, RMissing lengthOut, RMissing alongWith) { + startLengthOne(start); + toLengthOne(to); validateParams(start, to); - return RDataFactory.createIntSequence(start.getDataAt(0), stride, Math.abs((to.getDataAt(0) - start.getDataAt(0)) / stride) + 1); + if (topLengthProfile.profile(zero(start, to))) { + return 0; + } else { + return RDataFactory.createIntSequence(start.getDataAt(0), stride.getDataAt(0), Math.abs((to.getDataAt(0) - start.getDataAt(0)) / stride.getDataAt(0)) + 1); + } } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!zero(start, to)"}) - protected RDoubleSequence seq(RAbstractIntVector start, RAbstractIntVector to, double stride, RMissing lengthOut, RMissing alongWith) { + @Specialization + protected Object seq(RAbstractIntVector start, RAbstractIntVector to, RAbstractDoubleVector stride, RMissing lengthOut, RMissing alongWith) { + startLengthOne(start); + toLengthOne(to); validateParams(start, to); - return RDataFactory.createDoubleSequence(RRuntime.int2double(start.getDataAt(0)), stride, (int) (Math.abs((to.getDataAt(0) - start.getDataAt(0)) / stride)) + 1); + if (topLengthProfile.profile(zero(start, to))) { + return 0; + } else { + return RDataFactory.createDoubleSequence(RRuntime.int2double(start.getDataAt(0)), stride.getDataAt(0), (int) (Math.abs((to.getDataAt(0) - start.getDataAt(0)) / stride.getDataAt(0))) + 1); + } } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!lengthZero(lengthOut)"}) + @Specialization protected RIntVector seq(RAbstractIntVector start, RAbstractIntVector to, RMissing stride, int lengthOut, RMissing alongWith) { - validateParams(start, to); - return getVectorWithComputedStride(start.getDataAt(0), to.getDataAt(0), RRuntime.int2double(lengthOut), ascending(start, to)); + startLengthOne(start); + toLengthOne(to); + if (topLengthProfile.profile(lengthOut == 0)) { + validateParams(start, to); + return RDataFactory.createEmptyIntVector(); + } else { + validateParams(start, to); + return getVectorWithComputedStride(start.getDataAt(0), to.getDataAt(0), RRuntime.int2double(lengthOut), ascending(start, to)); + } } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!lengthZero(lengthOut)"}) + @Specialization protected RIntVector seq(RAbstractIntVector start, RAbstractIntVector to, RMissing stride, double lengthOut, RMissing alongWith) { - validateParams(start, to); - return getVectorWithComputedStride(start.getDataAt(0), to.getDataAt(0), lengthOut, ascending(start, to)); - } - - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "lengthZero(lengthOut)"}) - protected RIntVector seqLengthZero(RAbstractIntVector start, RAbstractIntVector to, RMissing stride, int lengthOut, RMissing alongWith) { - validateParams(start, to); - return RDataFactory.createEmptyIntVector(); - } - - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "lengthZero(lengthOut)"}) - protected RIntVector seqLengthZero(RAbstractIntVector start, RAbstractIntVector to, RMissing stride, double lengthOut, RMissing alongWith) { - validateParams(start, to); - return RDataFactory.createEmptyIntVector(); - } - - @Specialization(guards = {"startLengthOne(start)", "lengthZeroAlong(alongWith)"}) - protected RIntVector seq(RAbstractIntVector start, RMissing to, RMissing stride, Object lengthOut, RAbstractVector alongWith) { - validateParam(start.getDataAt(0), "from"); - return RDataFactory.createEmptyIntVector(); + startLengthOne(start); + toLengthOne(to); + if (topLengthProfile.profile(lengthOut == 0)) { + validateParams(start, to); + return RDataFactory.createEmptyIntVector(); + } else { + validateParams(start, to); + return getVectorWithComputedStride(start.getDataAt(0), to.getDataAt(0), lengthOut, ascending(start, to)); + } } - @Specialization(guards = {"startLengthOne(start)", "!lengthZeroAlong(alongWith)"}) - protected RDoubleSequence seqLengthZero(RAbstractIntVector start, RMissing to, RMissing stride, Object lengthOut, RAbstractVector alongWith) { - validateParam(start.getDataAt(0), "from"); - return RDataFactory.createDoubleSequence(start.getDataAt(0), 1, alongWith.getLength()); + @Specialization + protected RAbstractVector seq(RAbstractIntVector start, RMissing to, RMissing stride, Object lengthOut, RAbstractVector alongWith) { + startLengthOne(start); + if (topLengthProfile.profile(alongWith.getLength() == 0)) { + validateParam(start.getDataAt(0), "from"); + return RDataFactory.createEmptyIntVector(); + } else { + validateParam(start.getDataAt(0), "from"); + return RDataFactory.createDoubleSequence(start.getDataAt(0), 1, alongWith.getLength()); + } } // int vector start, double vector to - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "zero(start, to)"}) - protected int seqZero(RAbstractIntVector start, RAbstractDoubleVector to, Object stride, RMissing lengthOut, RMissing alongWith) { - return 0; - } - - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!zero(start, to)"}) - protected RIntSequence seq(RAbstractIntVector start, RAbstractDoubleVector to, RMissing stride, RMissing lengthOut, RMissing alongWith) { - validateParams(start, to); - return RDataFactory.createIntSequence(start.getDataAt(0), ascending(start, to) ? 1 : -1, (int) Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1); - } - - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!zero(start, to)"}) - protected RDoubleSequence seq(RAbstractIntVector start, RAbstractDoubleVector to, int stride, RMissing lengthOut, RMissing alongWith) { - validateParams(start, to); - int length = (int) Math.abs(to.getDataAt(0) - start.getDataAt(0)) / stride; - if (start.getDataAt(0) + length * stride == to.getDataAt(0)) { - length++; - } - return RDataFactory.createDoubleSequence(start.getDataAt(0), stride, length); - } - - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!zero(start, to)"}) - protected RDoubleSequence seq(RAbstractIntVector start, RAbstractDoubleVector to, double stride, RMissing lengthOut, RMissing alongWith) { + @Specialization + protected Object seq(RAbstractIntVector start, RAbstractDoubleVector to, RMissing stride, RMissing lengthOut, RMissing alongWith) { + startLengthOne(start); + toLengthOne(to); validateParams(start, to); - int length = (int) (Math.abs(to.getDataAt(0) - start.getDataAt(0)) / stride); - if (start.getDataAt(0) + length * stride == to.getDataAt(0)) { - length++; + if (topLengthProfile.profile(zero(start, to))) { + return 0; + } else { + return RDataFactory.createIntSequence(start.getDataAt(0), ascending(start, to) ? 1 : -1, (int) Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1); } - return RDataFactory.createDoubleSequence(start.getDataAt(0), stride, length); } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "lengthZero(lengthOut)"}) - protected RIntVector seqLengthZero(RAbstractIntVector start, RAbstractDoubleVector to, RMissing stride, int lengthOut, RMissing alongWith) { - validateParams(start, to); - return RDataFactory.createEmptyIntVector(); + @Specialization + protected Object seq(RAbstractIntVector start, RAbstractDoubleVector to, RAbstractIntVector stride, RMissing lengthOut, RMissing alongWith) { + return seq(start, to, RClosures.createIntToDoubleVector(stride), lengthOut, alongWith); } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!lengthZero(lengthOut)"}) - protected RDoubleVector seq(RAbstractIntVector start, RAbstractDoubleVector to, RMissing stride, int lengthOut, RMissing alongWith) { + @Specialization + protected Object seq(RAbstractIntVector start, RAbstractDoubleVector to, RAbstractDoubleVector stride, RMissing lengthOut, RMissing alongWith) { + startLengthOne(start); + toLengthOne(to); validateParams(start, to); - return getVectorWithComputedStride(RRuntime.int2double(start.getDataAt(0)), to.getDataAt(0), lengthOut, ascending(start, to)); + if (topLengthProfile.profile(zero(start, to))) { + return 0; + } else { + int length = (int) (Math.abs(to.getDataAt(0) - start.getDataAt(0)) / stride.getDataAt(0)); + if (start.getDataAt(0) + length * stride.getDataAt(0) == to.getDataAt(0)) { + length++; + } + return RDataFactory.createDoubleSequence(start.getDataAt(0), stride.getDataAt(0), length); + } } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "lengthZero(lengthOut)"}) - protected RIntVector seqLengthZero(RAbstractIntVector start, RAbstractDoubleVector to, RMissing stride, double lengthOut, RMissing alongWith) { + @Specialization + protected RAbstractVector seqLengthZero(RAbstractIntVector start, RAbstractDoubleVector to, RMissing stride, int lengthOut, RMissing alongWith) { + startLengthOne(start); + toLengthOne(to); validateParams(start, to); - return RDataFactory.createEmptyIntVector(); + if (topLengthProfile.profile(lengthOut == 0)) { + return RDataFactory.createEmptyIntVector(); + } else { + return getVectorWithComputedStride(RRuntime.int2double(start.getDataAt(0)), to.getDataAt(0), lengthOut, ascending(start, to)); + } } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!lengthZero(lengthOut)"}) - protected RDoubleVector seq(RAbstractIntVector start, RAbstractDoubleVector to, RMissing stride, double lengthOut, RMissing alongWith) { + @Specialization + protected RAbstractVector seqLengthZero(RAbstractIntVector start, RAbstractDoubleVector to, RMissing stride, double lengthOut, RMissing alongWith) { + startLengthOne(start); + toLengthOne(to); validateParams(start, to); - return getVectorWithComputedStride(RRuntime.int2double(start.getDataAt(0)), to.getDataAt(0), lengthOut, ascending(start, to)); + if (topLengthProfile.profile(lengthOut == 0)) { + return RDataFactory.createEmptyIntVector(); + } else { + return getVectorWithComputedStride(RRuntime.int2double(start.getDataAt(0)), to.getDataAt(0), lengthOut, ascending(start, to)); + } } // double vector start, missing to - @Specialization(guards = "!startEmpty(start)") - protected RDoubleSequence seqFromOneArg(RAbstractDoubleVector start, RMissing to, RMissing stride, RMissing lengthOut, RMissing alongWith) { - validateParam(start.getDataAt(0), "from"); - // GNU R really does that (take the length of start to create a sequence) - return RDataFactory.createDoubleSequence(1, 1, start.getLength()); - } - - @Specialization(guards = "startEmpty(start)") - protected RIntVector seqFromOneArgEmpty(RAbstractDoubleVector start, RMissing to, RMissing stride, RMissing lengthOut, RMissing alongWith) { - return RDataFactory.createEmptyIntVector(); - } - - @Specialization(guards = {"startLengthOne(start)", "!lengthZero(lengthOut)"}) - protected RDoubleSequence seqLengthZero(RAbstractDoubleVector start, RMissing to, RMissing stride, int lengthOut, RMissing alongWith) { - validateParam(start.getDataAt(0), "from"); - return RDataFactory.createDoubleSequence(start.getDataAt(0), 1, lengthOut); - } - - @Specialization(guards = {"startLengthOne(start)", "!lengthZero(lengthOut)"}) - protected RDoubleSequence seqLengthZero(RAbstractDoubleVector start, RMissing to, RMissing stride, double lengthOut, RMissing alongWith) { - validateParam(start.getDataAt(0), "from"); - return RDataFactory.createDoubleSequence(start.getDataAt(0), 1, (int) Math.ceil(lengthOut)); - } - - @Specialization(guards = {"startLengthOne(start)", "lengthZero(lengthOut)"}) - protected RIntVector seq(RAbstractDoubleVector start, RMissing to, RMissing stride, int lengthOut, RMissing alongWith) { - validateParam(start.getDataAt(0), "from"); - return RDataFactory.createEmptyIntVector(); + @Specialization + protected RAbstractVector seqFromOneArg(RAbstractDoubleVector start, RMissing to, RMissing stride, RMissing lengthOut, RMissing alongWith) { + if (topLengthProfile.profile(start.getLength() == 0)) { + return RDataFactory.createEmptyIntVector(); + } else { + validateParam(start.getDataAt(0), "from"); + // GNU R really does that (take the length of start to create a sequence) + return RDataFactory.createDoubleSequence(1, 1, start.getLength()); + } } - @Specialization(guards = {"startLengthOne(start)", "lengthZero(lengthOut)"}) - protected RIntVector seq(RAbstractDoubleVector start, RMissing to, RMissing stride, double lengthOut, RMissing alongWith) { + @Specialization + protected RAbstractVector seqStartLengthOne(RAbstractDoubleVector start, RMissing to, RMissing stride, int lengthOut, RMissing alongWith) { + startLengthOne(start); validateParam(start.getDataAt(0), "from"); - return RDataFactory.createEmptyIntVector(); + if (topLengthProfile.profile(lengthOut == 0)) { + return RDataFactory.createEmptyIntVector(); + } else { + return RDataFactory.createDoubleSequence(start.getDataAt(0), 1, lengthOut); + } } - @Specialization(guards = {"startLengthOne(start)", "lengthZeroAlong(alongWith)"}) - protected RIntVector seq(RAbstractDoubleVector start, RMissing to, RMissing stride, Object lengthOut, RAbstractVector alongWith) { + @Specialization + protected RAbstractVector seqStartLengthOne(RAbstractDoubleVector start, RMissing to, RMissing stride, double lengthOut, RMissing alongWith) { + startLengthOne(start); validateParam(start.getDataAt(0), "from"); - return RDataFactory.createEmptyIntVector(); + if (topLengthProfile.profile(lengthOut == 0)) { + return RDataFactory.createEmptyIntVector(); + } else { + return RDataFactory.createDoubleSequence(start.getDataAt(0), 1, (int) Math.ceil(lengthOut)); + } } - @Specialization(guards = {"startLengthOne(start)", "!lengthZeroAlong(alongWith)"}) - protected RDoubleSequence seqLengthZero(RAbstractDoubleVector start, RMissing to, RMissing stride, Object lengthOut, RAbstractVector alongWith) { + @Specialization + protected RAbstractVector seqStartLengthOne(RAbstractDoubleVector start, RMissing to, RMissing stride, Object lengthOut, RAbstractVector alongWith) { + startLengthOne(start); validateParam(start.getDataAt(0), "from"); - return RDataFactory.createDoubleSequence(start.getDataAt(0), 1, alongWith.getLength()); + if (topLengthProfile.profile(alongWith.getLength() == 0)) { + return RDataFactory.createEmptyIntVector(); + } else { + return RDataFactory.createDoubleSequence(start.getDataAt(0), 1, alongWith.getLength()); + } } // double vector start, int vector to - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "zero(start, to)"}) - protected int seqZero(RAbstractDoubleVector start, RAbstractIntVector to, Object stride, RMissing lengthOut, RMissing alongWith) { - return 0; - } - - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!zero(start, to)"}) - protected RAbstractVector seq(RAbstractDoubleVector start, RAbstractIntVector to, RMissing stride, RMissing lengthOut, RMissing alongWith) { + @Specialization + protected Object seq(RAbstractDoubleVector start, RAbstractIntVector to, RMissing stride, RMissing lengthOut, RMissing alongWith, + @Cached("createBinaryProfile()") ConditionProfile intProfile) { + startLengthOne(start); + toLengthOne(to); validateParams(start, to); - if ((int) start.getDataAt(0) == start.getDataAt(0)) { - return RDataFactory.createIntSequence((int) start.getDataAt(0), ascending(start, to) ? 1 : -1, (int) (Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1)); + if (topLengthProfile.profile(zero(start, to))) { + return 0; } else { - return RDataFactory.createDoubleSequence(start.getDataAt(0), ascending(start, to) ? 1 : -1, (int) (Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1)); + if (intProfile.profile((int) start.getDataAt(0) == start.getDataAt(0))) { + return RDataFactory.createIntSequence((int) start.getDataAt(0), ascending(start, to) ? 1 : -1, (int) (Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1)); + } else { + return RDataFactory.createDoubleSequence(start.getDataAt(0), ascending(start, to) ? 1 : -1, (int) (Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1)); + } } } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!zero(start, to)"}) - protected RDoubleSequence seq(RAbstractDoubleVector start, RAbstractIntVector to, int stride, RMissing lengthOut, RMissing alongWith) { - validateParams(start, to); - return RDataFactory.createDoubleSequence(start.getDataAt(0), stride, (int) Math.abs((to.getDataAt(0) - start.getDataAt(0)) / stride) + 1); - } - - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!zero(start, to)"}) - protected RDoubleSequence seq(RAbstractDoubleVector start, RAbstractIntVector to, double stride, RMissing lengthOut, RMissing alongWith) { - validateParams(start, to); - return RDataFactory.createDoubleSequence(start.getDataAt(0), stride, (int) Math.abs((to.getDataAt(0) - start.getDataAt(0)) / stride) + 1); - } - - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "lengthZero(lengthOut)"}) - protected RIntVector seqLengthZero(RAbstractDoubleVector start, RAbstractIntVector to, RMissing stride, int lengthOut, RMissing alongWith) { - validateParams(start, to); - return RDataFactory.createEmptyIntVector(); + @Specialization + protected Object seq(RAbstractDoubleVector start, RAbstractIntVector to, RAbstractIntVector stride, RMissing lengthOut, RMissing alongWith) { + return seq(start, to, RClosures.createIntToDoubleVector(stride), lengthOut, alongWith); } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!lengthZero(lengthOut)"}) - protected RDoubleVector seq(RAbstractDoubleVector start, RAbstractIntVector to, RMissing stride, int lengthOut, RMissing alongWith) { + @Specialization + protected Object seq(RAbstractDoubleVector start, RAbstractIntVector to, RAbstractDoubleVector stride, RMissing lengthOut, RMissing alongWith) { + startLengthOne(start); + toLengthOne(to); validateParams(start, to); - return getVectorWithComputedStride(start.getDataAt(0), RRuntime.int2double(to.getDataAt(0)), lengthOut, ascending(start, to)); + if (topLengthProfile.profile(zero(start, to))) { + return 0; + } else { + return RDataFactory.createDoubleSequence(start.getDataAt(0), stride.getDataAt(0), (int) Math.abs((to.getDataAt(0) - start.getDataAt(0)) / stride.getDataAt(0)) + 1); + } } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "lengthZero(lengthOut)"}) - protected RIntVector seqLengthZero(RAbstractDoubleVector start, RAbstractIntVector to, RMissing stride, double lengthOut, RMissing alongWith) { - validateParams(start, to); - return RDataFactory.createEmptyIntVector(); + @Specialization + protected RAbstractVector seqLengthZero(RAbstractDoubleVector start, RAbstractIntVector to, RMissing stride, int lengthOut, RMissing alongWith) { + startLengthOne(start); + toLengthOne(to); + if (topLengthProfile.profile(lengthOut == 0)) { + validateParams(start, to); + return RDataFactory.createEmptyIntVector(); + } else { + validateParams(start, to); + return getVectorWithComputedStride(start.getDataAt(0), RRuntime.int2double(to.getDataAt(0)), lengthOut, ascending(start, to)); + } } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!lengthZero(lengthOut)"}) - protected RDoubleVector seq(RAbstractDoubleVector start, RAbstractIntVector to, RMissing stride, double lengthOut, RMissing alongWith) { - validateParams(start, to); - return getVectorWithComputedStride(start.getDataAt(0), RRuntime.int2double(to.getDataAt(0)), lengthOut, ascending(start, to)); + @Specialization + protected RAbstractVector seqLengthZero(RAbstractDoubleVector start, RAbstractIntVector to, RMissing stride, double lengthOut, RMissing alongWith) { + startLengthOne(start); + toLengthOne(to); + if (topLengthProfile.profile(lengthOut == 0)) { + validateParams(start, to); + return RDataFactory.createEmptyIntVector(); + } else { + validateParams(start, to); + return getVectorWithComputedStride(start.getDataAt(0), RRuntime.int2double(to.getDataAt(0)), lengthOut, ascending(start, to)); + } } // double vector start, double vector to - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "zero(start, to)"}) - protected double seq(RAbstractDoubleVector start, RAbstractDoubleVector to, Object stride, RMissing lengthOut, RMissing alongWith) { - return 0; - } - - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!zero(start, to)"}) - protected RAbstractVector seq(RAbstractDoubleVector start, RAbstractDoubleVector to, RMissing stride, RMissing lengthOut, RMissing alongWith) { + @Specialization + protected Object seq(RAbstractDoubleVector start, RAbstractDoubleVector to, RMissing stride, RMissing lengthOut, RMissing alongWith, // + @Cached("createBinaryProfile()") ConditionProfile intProfile) { + startLengthOne(start); + toLengthOne(to); validateParams(start, to); - if ((int) start.getDataAt(0) == start.getDataAt(0) && (int) to.getDataAt(0) == to.getDataAt(0)) { - return RDataFactory.createIntSequence((int) start.getDataAt(0), ascending(start, to) ? 1 : -1, (int) (Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1)); + if (topLengthProfile.profile(zero(start, to))) { + return 0; } else { - return RDataFactory.createDoubleSequence(start.getDataAt(0), ascending(start, to) ? 1 : -1, (int) (Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1)); + if (intProfile.profile((int) start.getDataAt(0) == start.getDataAt(0) && (int) to.getDataAt(0) == to.getDataAt(0))) { + return RDataFactory.createIntSequence((int) start.getDataAt(0), ascending(start, to) ? 1 : -1, (int) (Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1)); + } else { + return RDataFactory.createDoubleSequence(start.getDataAt(0), ascending(start, to) ? 1 : -1, (int) (Math.abs(to.getDataAt(0) - start.getDataAt(0)) + 1)); + } } } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!zero(start, to)"}) - protected RDoubleSequence seq(RAbstractDoubleVector start, RAbstractDoubleVector to, int stride, RMissing lengthOut, RMissing alongWith) { - validateParams(start, to); - return RDataFactory.createDoubleSequence(start.getDataAt(0), stride, (int) (Math.abs((to.getDataAt(0) - start.getDataAt(0)) / stride) + 1)); - } - - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!zero(start, to)"}) - protected RDoubleSequence seq(RAbstractDoubleVector start, RAbstractDoubleVector to, double stride, RMissing lengthOut, RMissing alongWith) { - validateParams(start, to); - return RDataFactory.createDoubleSequence(start.getDataAt(0), stride, (int) (Math.abs((to.getDataAt(0) - start.getDataAt(0)) / stride) + 1)); - } - - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!lengthZero(lengthOut)"}) - protected RDoubleVector seq(RAbstractDoubleVector start, RAbstractDoubleVector to, RMissing stride, int lengthOut, RMissing alongWith) { - validateParams(start, to); - return getVectorWithComputedStride(start.getDataAt(0), to.getDataAt(0), RRuntime.int2double(lengthOut), ascending(start, to)); + @Specialization + protected Object seq(RAbstractDoubleVector start, RAbstractDoubleVector to, RAbstractIntVector stride, RMissing lengthOut, RMissing alongWith) { + return seq(start, to, RClosures.createIntToDoubleVector(stride), lengthOut, alongWith); } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "lengthZero(lengthOut)"}) - protected RIntVector seqLengthZero(RAbstractDoubleVector start, RAbstractDoubleVector to, RMissing stride, int lengthOut, RMissing alongWith) { + @Specialization + protected Object seq(RAbstractDoubleVector start, RAbstractDoubleVector to, RAbstractDoubleVector stride, RMissing lengthOut, RMissing alongWith) { + startLengthOne(start); + toLengthOne(to); validateParams(start, to); - return RDataFactory.createEmptyIntVector(); + if (topLengthProfile.profile(zero(start, to))) { + return 0; + } else { + return RDataFactory.createDoubleSequence(start.getDataAt(0), stride.getDataAt(0), (int) (Math.abs((to.getDataAt(0) - start.getDataAt(0)) / stride.getDataAt(0)) + 1)); + } } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!lengthZero(lengthOut)"}) - protected RDoubleVector seq(RAbstractDoubleVector start, RAbstractDoubleVector to, RMissing stride, double lengthOut, RMissing alongWith) { - validateParams(start, to); - return getVectorWithComputedStride(start.getDataAt(0), to.getDataAt(0), lengthOut, ascending(start, to)); + @Specialization + protected RAbstractVector seqLengthZero(RAbstractDoubleVector start, RAbstractDoubleVector to, RMissing stride, int lengthOut, RMissing alongWith) { + startLengthOne(start); + toLengthOne(to); + if (topLengthProfile.profile(lengthOut == 0)) { + validateParams(start, to); + return RDataFactory.createEmptyIntVector(); + } else { + validateParams(start, to); + return getVectorWithComputedStride(start.getDataAt(0), to.getDataAt(0), RRuntime.int2double(lengthOut), ascending(start, to)); + } } - @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "lengthZero(lengthOut)"}) - protected RIntVector seqLengthZero(RAbstractDoubleVector start, RAbstractDoubleVector to, RMissing stride, double lengthOut, RMissing alongWith) { - validateParams(start, to); - return RDataFactory.createEmptyIntVector(); + @Specialization + protected RAbstractVector seqLengthZero(RAbstractDoubleVector start, RAbstractDoubleVector to, RMissing stride, double lengthOut, RMissing alongWith) { + startLengthOne(start); + toLengthOne(to); + if (topLengthProfile.profile(lengthOut == 0)) { + validateParams(start, to); + return RDataFactory.createEmptyIntVector(); + } else { + validateParams(start, to); + return getVectorWithComputedStride(start.getDataAt(0), to.getDataAt(0), lengthOut, ascending(start, to)); + } } // logical vectors - private final NACheck naCheck = NACheck.create(); - @Specialization protected Object seq(RAbstractLogicalVector start, RAbstractLogicalVector to, Object stride, Object lengthOut, Object alongWith) { return seqRecursive(RClosures.createLogicalToDoubleVector(start), RClosures.createLogicalToDoubleVector(to), stride, lengthOut, alongWith); @@ -528,122 +572,57 @@ public abstract class Seq extends RBuiltinNode { return v.getElementClass() == RLogical.class; } - // @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "zero(start, to)"}) - // protected double seq(RAbstractLogicalVector start, RAbstractLogicalVector to, Object stride, - // RMissing lengthOut, RMissing alongWith) { - // controlVisibility(); - // return 0; - // } - // - // @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", "!zero(start, to)"}) - // protected RIntSequence seq(RAbstractLogicalVector start, RAbstractLogicalVector to, RMissing - // stride, RMissing lengthOut, RMissing alongWith) { - // controlVisibility(); - // validateParams(start, to); - // return RDataFactory.createIntSequence(RRuntime.logical2int(start.getDataAt(0)), - // ascending(start, - // to) ? 1 : -1, - // Math.abs(RRuntime.logical2int(to.getDataAt(0)) - RRuntime.logical2int(start.getDataAt(0))) + - // 1); - // } - // - // @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", - // "!lengthZero(lengthOut)"}) - // protected RDoubleVector seq(RAbstractLogicalVector start, RAbstractLogicalVector to, RMissing - // stride, int lengthOut, RMissing alongWith) { - // controlVisibility(); - // validateParams(start, to); - // return getVectorWithComputedStride(RRuntime.logical2double(start.getDataAt(0)), - // RRuntime.logical2double(to.getDataAt(0)), RRuntime.int2double(lengthOut), ascending(start, - // to)); - // } - // - // @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", - // "!lengthZero(lengthOut)"}) - // protected RDoubleVector seq(RAbstractLogicalVector start, RAbstractLogicalVector to, RMissing - // stride, double lengthOut, RMissing alongWith) { - // controlVisibility(); - // validateParams(start, to); - // return getVectorWithComputedStride(RRuntime.logical2double(start.getDataAt(0)), - // RRuntime.logical2double(to.getDataAt(0)), lengthOut, ascending(start, to)); - // } - // - // @Specialization(guards = {"startLengthOne(start)", "toLengthOne(to)", - // "lengthZero(lengthOut)"}) - // protected RIntVector seqLengthZero(RAbstractLogicalVector start, RAbstractLogicalVector to, - // RMissing stride, double lengthOut, RMissing alongWith) { - // controlVisibility(); - // validateParams(start, to); - // return RDataFactory.createEmptyIntVector(); - // } - // - // @Specialization(guards = "!startEmpty(start)") - // protected RIntSequence seqFromOneArg(RAbstractLogicalVector start, RMissing to, RMissing - // stride, - // RMissing lengthOut, RMissing alongWith) { - // controlVisibility(); - // validateParam(RRuntime.logical2int(start.getDataAt(0)), "to"); - // // GNU R really does that (take the length of start to create a sequence) - // return RDataFactory.createIntSequence(1, 1, start.getLength()); - // } - // - // @Specialization(guards = "startEmpty(start)") - // protected RIntVector seqFromOneArgEmpty(RAbstractLogicalVector start, RMissing to, RMissing - // stride, RMissing lengthOut, RMissing alongWith) { - // return RDataFactory.createEmptyIntVector(); - // } - - @Specialization(guards = "lengthZero(lengthOut)") - protected RIntVector seqLengthZero(RMissing start, RMissing to, RMissing stride, int lengthOut, RMissing alongWith) { - return RDataFactory.createEmptyIntVector(); - } - - @Specialization(guards = "!lengthZero(lengthOut)") - protected RIntSequence seq(RMissing start, RMissing to, RMissing stride, int lengthOut, RMissing alongWith) { - return RDataFactory.createIntSequence(1, 1, lengthOut); - } - - @Specialization(guards = "lengthZero(lengthOut)") - protected RIntVector seqLengthZero(RMissing start, RMissing to, RMissing stride, double lengthOut, RMissing alongWith) { - return RDataFactory.createEmptyIntVector(); - } - - @Specialization(guards = "!lengthZero(lengthOut)") - protected RIntSequence seq(RMissing start, RMissing to, RMissing stride, double lengthOut, RMissing alongWith) { - return RDataFactory.createIntSequence(1, 1, (int) Math.ceil(lengthOut)); - } - - @Specialization(guards = "lengthZeroAlong(alongWith)") - protected RIntVector seqLengthZeroAlong(RMissing start, RMissing to, RMissing stride, Object lengthOut, RAbstractVector alongWith) { - return RDataFactory.createEmptyIntVector(); - } - - @Specialization(guards = "!lengthZeroAlong(alongWith)") - protected RIntSequence seq(RMissing start, RMissing to, RMissing stride, Object lengthOut, RAbstractVector alongWith) { - return RDataFactory.createIntSequence(1, 1, alongWith.getLength()); - } - - @Specialization(guards = {"toLengthOne(to)", "positiveLengthOut(lengthOut)"}) + @Specialization + protected RAbstractVector seqLengthZero(RMissing start, RMissing to, RMissing stride, int lengthOut, RMissing alongWith) { + if (topLengthProfile.profile(lengthOut == 0)) { + return RDataFactory.createEmptyIntVector(); + } else { + return RDataFactory.createIntSequence(1, 1, lengthOut); + } + } + + @Specialization + protected RAbstractVector seqLengthZero(RMissing start, RMissing to, RMissing stride, double lengthOut, RMissing alongWith) { + if (topLengthProfile.profile(lengthOut == 0)) { + return RDataFactory.createEmptyIntVector(); + } else { + return RDataFactory.createIntSequence(1, 1, (int) Math.ceil(lengthOut)); + } + } + + @Specialization + protected RAbstractVector seqLengthZeroAlong(RMissing start, RMissing to, RMissing stride, Object lengthOut, RAbstractVector alongWith) { + if (topLengthProfile.profile(alongWith.getLength() == 0)) { + return RDataFactory.createEmptyIntVector(); + } else { + return RDataFactory.createIntSequence(1, 1, alongWith.getLength()); + } + } + + @Specialization protected RDoubleSequence seq(RMissing start, RAbstractIntVector to, RMissing stride, int lengthOut, RMissing alongWith) { + toLengthOne(to); + positiveLengthOut(lengthOut); validateParam(to.getDataAt(0), "to"); return RDataFactory.createDoubleSequence(to.getDataAt(0) - lengthOut + 1, 1, lengthOut); } - @Specialization(guards = {"toLengthOne(to)", "positiveLengthOut(lengthOut)"}) + @Specialization protected RDoubleSequence seq(RMissing start, RAbstractIntVector to, RMissing stride, double lengthOut, RMissing alongWith) { - validateParam(to.getDataAt(0), "to"); - final int intLength = (int) Math.ceil(lengthOut); - return RDataFactory.createDoubleSequence(to.getDataAt(0) - intLength + 1, 1, intLength); + return seq(start, to, stride, (int) Math.ceil(lengthOut), alongWith); } - @Specialization(guards = {"toLengthOne(to)", "positiveLengthOut(lengthOut)"}) + @Specialization protected RDoubleSequence seq(RMissing start, RAbstractDoubleVector to, RMissing stride, double lengthOut, RMissing alongWith) { + toLengthOne(to); + positiveLengthOut(lengthOut); validateParam(to.getDataAt(0), "to"); return RDataFactory.createDoubleSequence(to.getDataAt(0) - lengthOut + 1, 1, (int) Math.ceil(lengthOut)); } - @Specialization(guards = "toLengthOne(to)") + @Specialization protected Object seq(RMissing start, RAbstractVector to, Object stride, RMissing lengthOut, RMissing alongWith) { + toLengthOne(to); return seqRecursive(1.0, to, stride, lengthOut, alongWith); } @@ -683,12 +662,9 @@ public abstract class Seq extends RBuiltinNode { return start.getDataAt(0) == 0 && to.getDataAt(0) == 0; } - protected boolean startEmpty(RAbstractVector start) { - return start.getLength() == 0; - } - protected boolean startLengthOne(RAbstractVector start) { if (start.getLength() != 1) { + error.enter(); throw RError.error(this, RError.Message.MUST_BE_SCALAR, "from"); } return true; @@ -696,25 +672,15 @@ public abstract class Seq extends RBuiltinNode { protected boolean toLengthOne(RAbstractVector to) { if (to.getLength() != 1) { + error.enter(); throw RError.error(this, RError.Message.MUST_BE_SCALAR, "to"); } return true; } - protected boolean lengthZero(int lengthOut) { - return lengthOut == 0; - } - - protected boolean lengthZero(double lengthOut) { - return lengthOut == 0; - } - - protected boolean lengthZeroAlong(RAbstractVector alongWith) { - return alongWith.getLength() == 0; - } - protected boolean positiveLengthOut(int lengthOut) { if (lengthOut < 0) { + error.enter(); throw RError.error(this, RError.Message.MUST_BE_POSITIVE, "length.out"); } return true; @@ -722,6 +688,7 @@ public abstract class Seq extends RBuiltinNode { protected boolean positiveLengthOut(double lengthOut) { if (lengthOut < 0) { + error.enter(); throw RError.error(this, RError.Message.MUST_BE_POSITIVE, "length.out"); } return true; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqLen.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqLen.java index aa7a9ac0e0cc459b0a0c3fa3842c411a30b68d34..bdc0b6c2cb31ad26f9f10551fa301d789410b3fb 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqLen.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqLen.java @@ -22,38 +22,34 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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.BranchProfile; import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.RIntSequence; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @RBuiltin(name = "seq_len", kind = PRIMITIVE, parameterNames = {"length.out"}, behavior = PURE) public abstract class SeqLen extends RBuiltinNode { - private final BranchProfile lengthProblem = BranchProfile.create(); - @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(0); + // this is slightly different than what GNU R does as it will report coercion warning for: + // seq_len(c("7", "b")) + // GNU R (presumably) gets the first element before doing a coercion but I don't think we + // can do it with our API + casts.arg("length.out").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(gte(0), RError.Message.MUST_BE_COERCIBLE_INTEGER); } @Specialization - protected RIntSequence seqLen(RAbstractIntVector length) { - if (length.getLength() != 1) { - lengthProblem.enter(); - RError.warning(this, RError.Message.FIRST_ELEMENT_USED, "length.out"); - if (length.getLength() == 0) { - throw RError.error(this, RError.Message.MUST_BE_COERCIBLE_INTEGER); - } - } - return RDataFactory.createIntSequence(1, 1, length.getDataAt(0)); + protected RIntSequence seqLen(int length) { + return RDataFactory.createIntSequence(1, 1, 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 a4b3465b43cfc0d321fae8473efa1d4092d56249..c82ccf48af8b739cac5ab953c713476211f24c9d 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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; @@ -29,8 +30,8 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import java.io.IOException; 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.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; @@ -80,10 +81,19 @@ public class SerializeFunctions { throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); } } + + protected void connection(CastBuilder casts) { + casts.arg("con").mustBe(instanceOf(RConnection.class)); + } } - @RBuiltin(name = "unserializeFromConn", kind = INTERNAL, parameterNames = {"conn", "refhook"}, behavior = IO) + @RBuiltin(name = "unserializeFromConn", kind = INTERNAL, parameterNames = {"con", "refhook"}, behavior = IO) public abstract static class UnserializeFromConn extends Adapter { + @Override + protected void createCasts(CastBuilder casts) { + connection(casts); + } + @Specialization protected Object doUnserializeFromConn(RConnection conn, @SuppressWarnings("unused") RNull refhook) { return doUnserializeFromConnBase(conn, null); @@ -96,8 +106,15 @@ public class SerializeFunctions { } } - @RBuiltin(name = "serializeToConn", visibility = OFF, kind = INTERNAL, parameterNames = {"object", "conn", "ascii", "version", "refhook"}, behavior = IO) + @RBuiltin(name = "serializeToConn", visibility = OFF, kind = INTERNAL, parameterNames = {"object", "con", "ascii", "version", "refhook"}, behavior = IO) public abstract static class SerializeToConn extends Adapter { + @Override + protected void createCasts(CastBuilder casts) { + connection(casts); + casts.arg("ascii").mustBe(logicalValue(), RError.Message.ASCII_NOT_LOGICAL); + casts.arg("version").allowNull().mustBe(integerValue()); + } + @Specialization protected Object doSerializeToConn(Object object, RConnection conn, byte asciiLogical, RNull version, RNull refhook) { int type; @@ -112,8 +129,13 @@ public class SerializeFunctions { } } - @RBuiltin(name = "unserialize", kind = INTERNAL, parameterNames = {"conn", "refhook"}, behavior = IO) + @RBuiltin(name = "unserialize", kind = INTERNAL, parameterNames = {"con", "refhook"}, behavior = IO) public abstract static class Unserialize extends Adapter { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("con").mustBe(instanceOf(RConnection.class).or(instanceOf(RAbstractRawVector.class))); + } + @Specialization protected Object unSerialize(RConnection conn, @SuppressWarnings("unused") RNull refhook) { return doUnserializeFromConnBase(conn, null); @@ -125,8 +147,14 @@ public class SerializeFunctions { } } - @RBuiltin(name = "serialize", kind = INTERNAL, parameterNames = {"object", "conn", "type", "version", "refhook"}, behavior = IO) + @RBuiltin(name = "serialize", kind = INTERNAL, parameterNames = {"object", "con", "type", "version", "refhook"}, behavior = IO) public abstract static class Serialize extends Adapter { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("con").allowNull().mustBe(instanceOf(RConnection.class)); + casts.arg("type").asIntegerVector().findFirst(); + } + @Specialization protected Object serialize(Object object, RConnection conn, int type, RNull version, RNull refhook) { return doSerializeToConnBase(object, conn, type, RRuntime.LOGICAL_NA, version, refhook); @@ -139,15 +167,16 @@ public class SerializeFunctions { return RDataFactory.createRawVector(data); } - @SuppressWarnings("unused") - @Fallback - protected Object serialize(Object object, Object conn, Object asciiLogical, Object version, Object refhook) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); - } } - @RBuiltin(name = "serializeb", kind = INTERNAL, parameterNames = {"object", "conn", "xdr", "version", "refhook"}, behavior = IO) + @RBuiltin(name = "serializeb", kind = INTERNAL, parameterNames = {"object", "con", "xdr", "version", "refhook"}, behavior = IO) public abstract static class SerializeB extends Adapter { + @Override + protected void createCasts(CastBuilder casts) { + connection(casts); + casts.arg("xdr").asLogicalVector().findFirst(); + } + @Specialization protected Object serializeB(Object object, RConnection conn, byte xdrLogical, RNull version, RNull refhook) { if (!RRuntime.fromLogical(xdrLogical)) { 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 552c317a2903d1f017404e1a35629a12bb6b1ea2..766d4fa8206990008ebce258aa6f296b0f8d9714 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -32,14 +33,11 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.objects.AsS4; import com.oracle.truffle.r.nodes.objects.AsS4NodeGen; 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.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RSequence; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; @RBuiltin(name = "setS4Object", kind = INTERNAL, parameterNames = {"object", "flag", "complete"}, behavior = PURE) public abstract class SetS4Object extends RBuiltinNode { @@ -48,25 +46,15 @@ public abstract class SetS4Object extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toAttributable(0, true, true, true); - casts.toLogical(1); - casts.toInteger(2); - } - - private boolean checkArgs(RAbstractLogicalVector flagVec, RAbstractIntVector completeVec) { - if (flagVec.getLength() == 0 || (flagVec.getLength() == 1 && flagVec.getDataAt(0) == RRuntime.LOGICAL_NA) || flagVec.getLength() > 1) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "flag"); - } - if (completeVec.getLength() == 0 || flagVec.getDataAt(0) == RRuntime.LOGICAL_NA) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "complete"); - } - return RRuntime.fromLogical(flagVec.getDataAt(0)); + casts.arg("object").allowNull().asAttributable(true, true, true); + casts.arg("flag").asLogicalVector().mustBe(singleElement(), RError.SHOW_CALLER, 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"); } @Specialization @TruffleBoundary - protected RNull asS4(RNull object, RAbstractLogicalVector flagVec, RAbstractIntVector completeVec) { - boolean flag = checkArgs(flagVec, completeVec); + protected RNull asS4(RNull object, boolean flag, @SuppressWarnings("unused") int complete) { if (flag) { RContext.getInstance().setNullS4Object(true); } else { @@ -80,14 +68,13 @@ public abstract class SetS4Object extends RBuiltinNode { } @Specialization(guards = "!isSequence(object)") - protected Object asS4(RAttributable object, RAbstractLogicalVector flagVec, RAbstractIntVector completeVec) { - boolean flag = checkArgs(flagVec, completeVec); - return asS4.executeObject(object, flag, completeVec.getDataAt(0)); + protected Object asS4(RAttributable object, boolean flag, int complete) { + return asS4.executeObject(object, flag, complete); } @Specialization - protected Object asS4(RSequence seq, RAbstractLogicalVector flagVec, RAbstractIntVector completeVec) { - return asS4(seq.materialize(), flagVec, completeVec); + protected Object asS4(RSequence seq, boolean flag, int complete) { + return asS4(seq.materialize(), flag, complete); } protected boolean isSequence(Object o) { 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 4eb04d2dfb03d1510bf49fd5581e53c0a29c5027..61e0a0edaf5a66fe8db29e29cfc1ad77115ca4b4 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 @@ -22,10 +22,12 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RNull; @@ -33,9 +35,16 @@ import com.oracle.truffle.r.runtime.data.RNull; @RBuiltin(name = "setTimeLimit", kind = INTERNAL, parameterNames = {"cpu", "elapsed", "transient"}, behavior = COMPLEX) public abstract class SetTimeLimit extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("cpu").asDoubleVector().findFirst(); + casts.arg("elapsed").asDoubleVector().findFirst(); + casts.arg("transient").asLogicalVector().findFirst().map(toBoolean()); + } + @SuppressWarnings("unused") @Specialization - protected RNull setTimeLimit(Object cpu, Object elapsed, Object trans) { + protected RNull setTimeLimit(double cpu, double elapsed, boolean trans) { // TODO: proper implementation sets timers checked during user interrupts that we currently // do not support return RNull.instance; 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 b1d5e64be3a77ba5cc703c5ef6375eeb816e739f..9180e76850957de0adc25607cb1ceccbad79fb3b 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 @@ -22,31 +22,36 @@ */ 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; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; 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.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; @RBuiltin(name = "setwd", visibility = OFF, kind = INTERNAL, parameterNames = "path", behavior = IO) public abstract class Setwd extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("path").defaultError(SHOW_CALLER, CHAR_ARGUMENT).mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst(); + } + @Specialization @TruffleBoundary - protected Object setwd(RAbstractStringVector path) { - if (path.getLength() == 0) { - throw RError.error(this, RError.Message.CHAR_ARGUMENT); - } + protected Object setwd(String path) { String owd = RFFIFactory.getRFFI().getBaseRFFI().getwd(); - String nwd = Utils.tildeExpand(path.getDataAt(0)); + String nwd = Utils.tildeExpand(path); int rc = RFFIFactory.getRFFI().getBaseRFFI().setwd(nwd); if (rc != 0) { throw RError.error(this, RError.Message.CANNOT_CHANGE_DIRECTORY); @@ -56,10 +61,4 @@ public abstract class Setwd extends RBuiltinNode { return owd; } } - - @Fallback - @TruffleBoundary - protected Object setwd(@SuppressWarnings("unused") Object path) { - throw RError.error(this, RError.Message.CHAR_ARGUMENT); - } } 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 ec1018bb70b44465fc6981f1f33a0d92d2dadd39..b057268ae0a62353576851b5f843e1ec705494a4 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 @@ -22,11 +22,12 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte0; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte; 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.frame.VirtualFrame; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.IntValueProfile; import com.oracle.truffle.api.profiles.ValueProfile; @@ -49,42 +50,27 @@ public abstract class ShortRowNames extends RBuiltinNode { private final BranchProfile errorProfile = BranchProfile.create(); private final ValueProfile operandTypeProfile = ValueProfile.createClassProfile(); - public abstract Object executeObject(VirtualFrame frame, Object operand, Object type); - @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1); + casts.arg("type").asIntegerVector().findFirst().mustBe(gte0().and(lte(2))); } private final IntValueProfile typeProfile = IntValueProfile.createIdentityProfile(); @Specialization - protected Object getNames(Object originalOperand, RAbstractIntVector originalType) { - - if (originalType.getLength() == 0) { - errorProfile.enter(); - throw typeError(); - } - int type = typeProfile.profile(originalType.getDataAt(0)); - - if (type < 0 || type > 2) { - errorProfile.enter(); - throw typeError(); - } - + protected Object getNames(Object originalOperand, int originalType) { Object operand = operandTypeProfile.profile(originalOperand); Object rowNames; if (operand instanceof RAbstractContainer) { rowNames = ((RAbstractContainer) operand).getRowNames(attrProfiles); } else if (operand instanceof REnvironment) { rowNames = ((REnvironment) operand).getAttr(attrProfiles, RRuntime.ROWNAMES_ATTR_KEY); - } else if (operand instanceof RNull) { - return 0; } else { - errorProfile.enter(); - throw typeError(); + // for any other type GnuR returns 0 + return 0; } + int type = typeProfile.profile(originalType); if (type >= 1) { int n = calculateN(rowNames); rowNames = type == 1 ? n : Math.abs(n); @@ -109,11 +95,7 @@ public abstract class ShortRowNames extends RBuiltinNode { return ((RAbstractContainer) rowNames).getLength(); } else { errorProfile.enter(); - throw typeError(); + throw RError.error(this, RError.Message.INVALID_ARGUMENT, "type"); } } - - private RError typeError() { - return RError.error(this, 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 f2662f5345c56f7e5b900898d61c5d9f21f787d2..f0c4adad1e2064a240d084694bc7f44d70360231 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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,14 +35,19 @@ 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.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.attributes.CopyAttributesNode; +import com.oracle.truffle.r.nodes.attributes.CopyAttributesNodeGen; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +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.builtins.RBuiltin; -import com.oracle.truffle.r.runtime.data.RAttributeProfiles; 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.ops.na.NACheck; @@ -54,57 +60,83 @@ public abstract class Signif extends RBuiltinNode { return new Object[]{RMissing.instance, 6}; } + @Child private CopyAttributesNode copyAttributes = CopyAttributesNodeGen.create(true); private final NACheck naCheck = NACheck.create(); + private final BranchProfile empty = BranchProfile.create(); private final BranchProfile identity = BranchProfile.create(); private final ConditionProfile infProfile = ConditionProfile.createBinaryProfile(); - private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1); + casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(numericValue().or(complexValue())).mapIf(complexValue().not(), + asDoubleVector(true, true, true)); + // TODO: for the error messages to be consistent with GNU R we should chack for notEmpty() + // first but it does not seem to be possible currently as numericValue() cannot be used on + // the result of asVector() + casts.arg("digits").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(numericValue()).asIntegerVector().mustBe(notEmpty(), RError.Message.INVALID_ARG_OF_LENGTH, "second", 0); } // TODO: consider porting signif implementation from GNU R - @Specialization(guards = "digitsVec.getLength() == 1") + @Specialization protected RAbstractDoubleVector signif(RAbstractDoubleVector x, RAbstractIntVector digitsVec) { - int digits = digitsVec.getDataAt(0) <= 0 ? 1 : digitsVec.getDataAt(0); - if (digits > 22) { - identity.enter(); - return x; + int xLength = x.getLength(); + if (x.getLength() == 0) { + empty.enter(); + return RDataFactory.createEmptyDoubleVector(); } - double[] data = new double[x.getLength()]; - naCheck.enable(x); - for (int i = 0; i < x.getLength(); i++) { - double val = x.getDataAt(i); - double result; - if (naCheck.check(val)) { - result = RRuntime.DOUBLE_NA; + int digitsVecLength = digitsVec.getLength(); + int maxLength = Math.max(xLength, digitsVecLength); + double[] data = new double[maxLength]; + int xInd = 0; + int digitsVecInd = 0; + for (int i = 0; i < maxLength; i++) { + int digits = digitsVec.getDataAt(digitsVecInd); + if (digits > 22) { + identity.enter(); + data[i] = x.getDataAt(xInd); } else { - if (infProfile.profile(Double.isInfinite(val))) { - result = Double.POSITIVE_INFINITY; + if (digits <= 0) { + digits = 1; + } + naCheck.enable(!(x.isComplete() && digitsVec.isComplete())); + double val = x.getDataAt(xInd); + double result; + if (naCheck.check(val)) { + result = RRuntime.DOUBLE_NA; + } else if (naCheck.check(digits)) { + result = RRuntime.DOUBLE_NA; } else { - result = bigIntegerSignif(digits, val); + if (infProfile.profile(Double.isInfinite(val))) { + result = Double.POSITIVE_INFINITY; + } else { + result = bigIntegerSignif(digits, val); + } } + data[i] = result; } - data[i] = result; + xInd = Utils.incMod(xInd, xLength); + digitsVecInd = Utils.incMod(digitsVecInd, digitsVecLength); } RDoubleVector ret = RDataFactory.createDoubleVector(data, naCheck.neverSeenNA()); - ret.copyAttributesFrom(attrProfiles, x); + ret = (RDoubleVector) copyAttributes.execute(ret, x, xLength, digitsVec, digitsVecLength); return ret; } + @SuppressWarnings("unused") + @Specialization + protected RAbstractComplexVector signif(RAbstractComplexVector x, RAbstractIntVector digitsVec) { + // TODO: implement for complex numbers but I am not sure GNU R gets it right: + // > signif(42.1234-7.1234i, 1) + // [1] 40-10i + + throw RInternalError.unimplemented(); + } + @TruffleBoundary private static double bigIntegerSignif(int digits, double val) { BigDecimal bigDecimalVal = new BigDecimal(val, new MathContext(digits, RoundingMode.HALF_UP)); return bigDecimalVal.doubleValue(); } - @Specialization(guards = "digits.getLength() == 1") - protected RAbstractIntVector roundDigits(RAbstractIntVector x, @SuppressWarnings("unused") RAbstractIntVector digits) { - return x; - } - - // TODO: add support for digit vectors of length different than 1 - } 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 467dccf6b4fe4ca36769573da7b07265cd6f3e7f..63bae90dc6e0cda03887b0cd17e2a47432be4641 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 @@ -22,6 +22,9 @@ */ 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.toBoolean; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; 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; @@ -29,34 +32,45 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import java.io.IOException; 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.CastBuilder; 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.conn.RConnection; import com.oracle.truffle.r.runtime.conn.StdConnections; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; public class SinkFunctions { - @RBuiltin(name = "sink", visibility = OFF, kind = INTERNAL, parameterNames = {"file", "closeOnExit", "isMessage", "split"}, behavior = IO) + @RBuiltin(name = "sink", visibility = OFF, kind = INTERNAL, parameterNames = {"file", "closeOnExit", "type", "split"}, behavior = IO) public abstract static class Sink extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("file").mustBe(instanceOf(RConnection.class).or(integerValue())); + casts.arg("closeOnExit").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("type").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("split").asLogicalVector().findFirst().notNA().map(toBoolean()); + } + @Specialization @TruffleBoundary - protected RNull sink(RConnection conn, byte closeOnExit, byte isMessage, @SuppressWarnings("unused") byte split) { - if (RRuntime.fromLogical(isMessage)) { + protected RNull sink(RConnection conn, boolean closeOnExit, boolean errcon, boolean split) { + if (split) { // TODO + throw RError.nyi(this, "split"); + } + if (errcon) { + StdConnections.divertErr(conn); } else { - StdConnections.pushDivertOut(conn, RRuntime.fromLogical(closeOnExit)); + StdConnections.pushDivertOut(conn, closeOnExit); } return RNull.instance; } @SuppressWarnings("unused") @Specialization - protected RNull sink(RAbstractIntVector conn, byte closeOnExit, byte isMessage, byte split) { + @TruffleBoundary + protected RNull sink(int conn, boolean closeOnExit, boolean isMessage, boolean split) { try { StdConnections.popDivertOut(); } catch (IOException ex) { @@ -65,29 +79,23 @@ public class SinkFunctions { return RNull.instance; } - @SuppressWarnings("unused") - @Fallback - protected RNull sink(Object conn, Object closeOnExit, Object isMessage, Object split) { - throw RError.error(this, RError.Message.INVALID_UNNAMED_ARGUMENTS); - } } @RBuiltin(name = "sink.number", kind = INTERNAL, parameterNames = {"type"}, behavior = IO) public abstract static class SinkNumber extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("type").asLogicalVector().findFirst().notNA().map(toBoolean()); + } + @Specialization @TruffleBoundary - protected int sinkNumber(byte isOutput) { - if (RRuntime.fromLogical(isOutput)) { + protected int sinkNumber(boolean isOutput) { + if (isOutput) { return StdConnections.stdoutDiversions(); } else { return StdConnections.stderrDiversion(); } } - - @SuppressWarnings("unused") - @Fallback - protected RNull sinkNumbner(Object type) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT); - } } } 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 c916d144022f5e7e3d863cf937e31b466d3735bc..2825463c7679da160107b42929f18bba1d333d5e 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 @@ -39,7 +39,7 @@ public abstract class Slot extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toAttributable(0, true, true, true); + casts.arg(0).allowNull().asAttributable(true, true, true); } private String getName(Object nameObj) { 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 19b7f6dab17953060c8f36a21ae44255191a1daa..ade5fa0e1f584c36896fdcc9aa81cb059b94655a 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 @@ -22,6 +22,12 @@ */ 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.numericValue; +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.ONLY_ATOMIC_CAN_BE_SORTED; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -29,11 +35,10 @@ import java.util.Arrays; import java.util.Collections; 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.CastBuilder; 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.RDoubleVector; @@ -53,11 +58,19 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; public class SortFunctions { private abstract static class Adapter extends RBuiltinNode { + protected static void addCastForX(CastBuilder castBuilder) { + castBuilder.arg("x").allowNull().mustBe(abstractVectorValue(), SHOW_CALLER, ONLY_ATOMIC_CAN_BE_SORTED); + } + + protected static void addCastForDecreasing(CastBuilder castBuilder) { + castBuilder.arg("decreasing").defaultError(SHOW_CALLER, INVALID_LOGICAL, "decreasing").mustBe(numericValue()).asLogicalVector().findFirst().map(toBoolean()); + } + @TruffleBoundary - private static double[] sort(double[] data, byte decreasing) { + private static double[] sort(double[] data, boolean decreasing) { // no reverse comparator for primitives Arrays.parallelSort(data); - if (RRuntime.fromLogical(decreasing)) { + if (decreasing) { int len = data.length; for (int i = len / 2 - 1; i >= 0; i--) { double temp = data[i]; @@ -69,9 +82,9 @@ public class SortFunctions { } @TruffleBoundary - private static int[] sort(int[] data, byte decreasing) { + private static int[] sort(int[] data, boolean decreasing) { Arrays.parallelSort(data); - if (RRuntime.fromLogical(decreasing)) { + if (decreasing) { int len = data.length; for (int i = len / 2 - 1; i >= 0; i--) { int temp = data[i]; @@ -83,9 +96,9 @@ public class SortFunctions { } @TruffleBoundary - private static byte[] sort(byte[] data, byte decreasing) { + private static byte[] sort(byte[] data, boolean decreasing) { Arrays.parallelSort(data); - if (RRuntime.fromLogical(decreasing)) { + if (decreasing) { int len = data.length; for (int i = len / 2 - 1; i >= 0; i--) { byte temp = data[i]; @@ -97,8 +110,8 @@ public class SortFunctions { } @TruffleBoundary - private static String[] sort(String[] data, byte decreasing) { - if (RRuntime.fromLogical(decreasing)) { + private static String[] sort(String[] data, boolean decreasing) { + if (decreasing) { Arrays.parallelSort(data, Collections.reverseOrder()); } else { Arrays.parallelSort(data); @@ -106,22 +119,22 @@ public class SortFunctions { return data; } - protected RDoubleVector jdkSort(RAbstractDoubleVector vec, byte decreasing) { + protected RDoubleVector jdkSort(RAbstractDoubleVector vec, boolean decreasing) { double[] data = vec.materialize().getDataCopy(); return RDataFactory.createDoubleVector(sort(data, decreasing), vec.isComplete()); } - protected RIntVector jdkSort(RAbstractIntVector vec, byte decreasing) { + protected RIntVector jdkSort(RAbstractIntVector vec, boolean decreasing) { int[] data = vec.materialize().getDataCopy(); return RDataFactory.createIntVector(sort(data, decreasing), vec.isComplete()); } - protected RStringVector jdkSort(RAbstractStringVector vec, byte decreasing) { + protected RStringVector jdkSort(RAbstractStringVector vec, boolean decreasing) { String[] data = vec.materialize().getDataCopy(); return RDataFactory.createStringVector(sort(data, decreasing), vec.isComplete()); } - protected RLogicalVector jdkSort(RAbstractLogicalVector vec, byte decreasing) { + protected RLogicalVector jdkSort(RAbstractLogicalVector vec, boolean decreasing) { byte[] data = vec.materialize().getDataCopy(); return RDataFactory.createLogicalVector(sort(data, decreasing), vec.isComplete()); } @@ -136,82 +149,95 @@ public class SortFunctions { */ @RBuiltin(name = "sort", kind = INTERNAL, parameterNames = {"x", "decreasing"}, behavior = PURE) public abstract static class Sort extends Adapter { - @Specialization - protected RDoubleVector sort(RAbstractDoubleVector vec, byte decreasing) { - return jdkSort(vec, decreasing); + + @Override + protected void createCasts(CastBuilder casts) { + addCastForX(casts); + addCastForDecreasing(casts); } @Specialization - protected RIntVector sort(RAbstractIntVector vec, byte decreasing) { + protected RDoubleVector sort(RAbstractDoubleVector vec, boolean decreasing) { return jdkSort(vec, decreasing); } @Specialization - protected RStringVector sort(RAbstractStringVector vec, byte decreasing) { + protected RIntVector sort(RAbstractIntVector vec, boolean decreasing) { return jdkSort(vec, decreasing); } @Specialization - protected RLogicalVector sort(RAbstractLogicalVector vec, byte decreasing) { + protected RStringVector sort(RAbstractStringVector vec, boolean decreasing) { return jdkSort(vec, decreasing); } - @SuppressWarnings("unused") - @Fallback - protected Object sort(Object vec, Object decreasing) { - throw RError.nyi(this, ".Internal(sort)"); + @Specialization + protected RLogicalVector sort(RAbstractLogicalVector vec, boolean decreasing) { + return jdkSort(vec, decreasing); } } @RBuiltin(name = "qsort", kind = INTERNAL, parameterNames = {"x", "decreasing"}, behavior = PURE) public abstract static class QSort extends Adapter { + @Override + protected void createCasts(CastBuilder casts) { + addCastForX(casts); + addCastForDecreasing(casts); + } + @Specialization - protected RDoubleVector qsort(RAbstractDoubleVector vec, byte decreasing) { + protected RDoubleVector qsort(RAbstractDoubleVector vec, boolean decreasing) { return jdkSort(vec, decreasing); } @Specialization - protected RIntVector qsort(RAbstractIntVector vec, byte decreasing) { + protected RIntVector qsort(RAbstractIntVector vec, boolean decreasing) { return jdkSort(vec, decreasing); } } @RBuiltin(name = "psort", kind = INTERNAL, parameterNames = {"x", "partial"}, behavior = PURE) public abstract static class PartialSort extends Adapter { + + @Override + protected void createCasts(CastBuilder casts) { + addCastForX(casts); + } + @SuppressWarnings("unused") @Specialization protected RDoubleVector sort(RAbstractDoubleVector vec, Object partial) { - return jdkSort(vec, RRuntime.LOGICAL_FALSE); + return jdkSort(vec, false); } @SuppressWarnings("unused") @Specialization protected RIntVector sort(RAbstractIntVector vec, Object partial) { - return jdkSort(vec, RRuntime.LOGICAL_FALSE); + return jdkSort(vec, false); } @SuppressWarnings("unused") @Specialization protected RStringVector sort(RAbstractStringVector vec, Object partial) { - return jdkSort(vec, RRuntime.LOGICAL_FALSE); + return jdkSort(vec, false); } @SuppressWarnings("unused") @Specialization protected RLogicalVector sort(RAbstractLogicalVector vec, Object partial) { - return jdkSort(vec, RRuntime.LOGICAL_FALSE); - } - - @SuppressWarnings("unused") - @Fallback - protected Object sort(Object x, Object partial) { - throw RError.nyi(this, ".Internal(psort)"); + return jdkSort(vec, false); } } @RBuiltin(name = "radixsort", kind = INTERNAL, parameterNames = {"zz", "na.last", "decreasing"}, behavior = PURE) - public abstract static class RadixSort extends RBuiltinNode { + public abstract static class RadixSort extends Adapter { + + @Override + protected void createCasts(CastBuilder casts) { + addCastForDecreasing(casts); + } + @SuppressWarnings("unused") @Specialization protected Object radixSort(Object zz, Object naLast, Object decreasing) { 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 753985e79b18a00b1517e436a7c09c8ff6849cf5..fb44ec8b4184b8d33ff20cb10def54fade00a160 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 @@ -12,10 +12,15 @@ */ 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.lengthGt; +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 java.util.function.Function; + import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.MaterializedFrame; @@ -28,6 +33,8 @@ import com.oracle.truffle.r.nodes.attributes.AttributeAccess; import com.oracle.truffle.r.nodes.attributes.AttributeAccessNodeGen; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.function.ClassHierarchyScalarNode; +import com.oracle.truffle.r.nodes.function.ClassHierarchyScalarNodeGen; import com.oracle.truffle.r.nodes.objects.CollectGenericArgumentsNode; import com.oracle.truffle.r.nodes.objects.CollectGenericArgumentsNodeGen; import com.oracle.truffle.r.nodes.objects.DispatchGeneric; @@ -39,15 +46,12 @@ 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.context.RContext; -import com.oracle.truffle.r.runtime.data.RAttributable; -import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RAttributes; 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.RStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; // transcribed from src/main/objects.c @@ -63,11 +67,12 @@ public abstract class StandardGeneric extends RBuiltinNode { @Child private LocalReadVariableNode readSigARgs = LocalReadVariableNode.create(RRuntime.DOT_SIG_ARGS, true); @Child private CollectGenericArgumentsNode collectArgumentsNode; @Child private DispatchGeneric dispatchGeneric = DispatchGenericNodeGen.create(); + @Child private ClassHierarchyScalarNode classNode; @Child private CastNode castIntScalar; @Child private CastNode castStringScalar; { - CastBuilder builder = new CastBuilder(); + CastBuilder builder = new CastBuilder(2); builder.arg(0).asIntegerVector().findFirst(RRuntime.INT_NA); builder.arg(1).asStringVector().findFirst(RRuntime.STRING_NA); castIntScalar = builder.getCasts()[0]; @@ -77,10 +82,23 @@ public abstract class StandardGeneric extends RBuiltinNode { private final BranchProfile noGenFunFound = BranchProfile.create(); private final ConditionProfile sameNamesProfile = ConditionProfile.createBinaryProfile(); - private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + private String argClass(Object arg) { + if (classNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + classNode = insert(ClassHierarchyScalarNodeGen.create()); + } + return classNode.executeString(arg); + } + + @Override + protected void createCasts(CastBuilder casts) { + 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 = this::argClass; + casts.arg("fdef").defaultError(RError.SHOW_CALLER, RError.Message.EXPECTED_GENERIC, argClass).allowMissing().asAttributable(true, true, true).mustBe(instanceOf(RFunction.class)); + } - private Object stdGenericInternal(VirtualFrame frame, RAbstractStringVector fVec, RFunction fdef) { - String fname = fVec.getDataAt(0); + private Object stdGenericInternal(VirtualFrame frame, String fname, RFunction fdef) { MaterializedFrame fnFrame = fdef.getEnclosingFrame(); REnvironment mtable = (REnvironment) readMTableFirst.execute(frame, fnFrame); if (mtable == null) { @@ -105,7 +123,7 @@ public abstract class StandardGeneric extends RBuiltinNode { return ret; } - private Object getFunction(VirtualFrame frame, RAbstractStringVector fVec, String fname, Object fnObj) { + private Object getFunction(VirtualFrame frame, String fname, Object fnObj) { if (fnObj == RNull.instance) { noGenFunFound.enter(); return null; @@ -128,7 +146,7 @@ public abstract class StandardGeneric extends RBuiltinNode { } String gen = (String) castStringScalar.execute(genObj); if (sameNamesProfile.profile(gen == fname)) { - return stdGenericInternal(frame, fVec, fn); + return stdGenericInternal(frame, fname, fn); } else { // in many cases == is good enough (and this will be the fastest path), but it's not // always sufficient @@ -136,21 +154,20 @@ public abstract class StandardGeneric extends RBuiltinNode { noGenFunFound.enter(); return null; } - return stdGenericInternal(frame, fVec, fn); + return stdGenericInternal(frame, fname, fn); } } - @Specialization(guards = "fVec.getLength() > 0") - protected Object stdGeneric(VirtualFrame frame, RAbstractStringVector fVec, RFunction fdef) { - return stdGenericInternal(frame, fVec, fdef); + @Specialization + protected Object stdGeneric(VirtualFrame frame, String fname, RFunction fdef) { + return stdGenericInternal(frame, fname, fdef); } - @Specialization(guards = "fVec.getLength() > 0") - protected Object stdGeneric(VirtualFrame frame, RAbstractStringVector fVec, @SuppressWarnings("unused") RMissing fdef) { - String fname = fVec.getDataAt(0); + @Specialization + protected Object stdGeneric(VirtualFrame frame, String fname, @SuppressWarnings("unused") RMissing fdef) { int n = RArguments.getDepth(frame); Object fnObj = RArguments.getFunction(frame); - fnObj = getFunction(frame, fVec, fname, fnObj); + fnObj = getFunction(frame, fname, fnObj); if (fnObj != null) { return fnObj; } @@ -161,10 +178,10 @@ public abstract class StandardGeneric extends RBuiltinNode { } // TODO: GNU R counts to (i < n) - does their equivalent of getDepth return a different // value - // TODO; shouldn't we count from n to 0? + // TODO: shouldn't we count from n to 0? for (int i = 0; i <= n; i++) { fnObj = sysFunction.executeObject(frame, i); - fnObj = getFunction(frame, fVec, fname, fnObj); + fnObj = getFunction(frame, fname, fnObj); if (fnObj != null) { return fnObj; } @@ -172,14 +189,4 @@ public abstract class StandardGeneric extends RBuiltinNode { throw RError.error(this, RError.Message.STD_GENERIC_WRONG_CALL, fname); } - @Specialization - protected Object stdGeneric(Object fVec, RAttributable fdef) { - if (!(fVec instanceof String || (fVec instanceof RAbstractStringVector && ((RAbstractStringVector) fVec).getLength() > 0))) { - throw RError.error(this, RError.Message.GENERIC, "argument to 'standardGeneric' must be a non-empty character string"); - } else { - RStringVector cl = fdef.getClassAttr(attrProfiles); - // not a GNU R error message - throw RError.error(this, RError.Message.EXPECTED_GENERIC, cl.getLength() == 0 ? RRuntime.STRING_NA : cl.getDataAt(0)); - } - } } 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 e8a0c744fb4d30711479e6942e1ad9f3c1b142e7..5e3b02e1532968c43043d37df862f19c73f67d5d 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 @@ -22,24 +22,34 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; 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.CastBuilder; 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.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.RNull; -@RBuiltin(name = "stop", kind = INTERNAL, parameterNames = {"call.", "message"}, behavior = COMPLEX) +@RBuiltin(name = "stop", kind = INTERNAL, parameterNames = {"call", "message"}, behavior = COMPLEX) public abstract class Stop extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("call").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("message").allowNull().mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.INVALID_STRING_IN_STOP).findFirst(); + } + + @Specialization + protected Object stop(boolean call, @SuppressWarnings("unused") RNull msgVec) { + throw stop(call, ""); + } @Specialization - protected Object stop(byte call, RAbstractStringVector msgVec) { - assert msgVec.getLength() == 1; + protected RError stop(boolean call, String message) throws RError { CompilerDirectives.transferToInterpreter(); - throw RError.stop(RRuntime.fromLogical(call), RError.SHOW_CALLER2, RError.Message.GENERIC, msgVec.getDataAt(0)); + throw RError.stop(call, RError.SHOW_CALLER2, RError.Message.GENERIC, message); } } 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 759459f1f09f5aec597075d536305be5d084bd9e..ce5653198a3d926047cf1bafafbb16a6b17e4808 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 @@ -22,57 +22,128 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.eq; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte; +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; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.ExactMath; +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.PrimitiveValueProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.ffi.RFFIFactory; @RBuiltin(name = "strtoi", kind = INTERNAL, parameterNames = {"x", "base"}, behavior = PURE) public abstract class Strtoi extends RBuiltinNode { + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(stringValue()).asStringVector(); + // base == 0 || (base >= 2 && base <= 36) + casts.arg("base").mustBe(integerValue()).asIntegerVector().findFirst().mustBe(eq(0).or(gte(2).and(lte(36)))); + } + @Specialization - @TruffleBoundary - protected RIntVector doStrtoi(RAbstractStringVector vec, int baseArg) { - int base = baseArg; + protected RIntVector doStrtoi(RAbstractStringVector vec, int baseArg, + @Cached("createBinaryProfile()") ConditionProfile emptyProfile, + @Cached("createBinaryProfile()") ConditionProfile baseZeroProfile, + @Cached("createBinaryProfile()") ConditionProfile negateProfile, + @Cached("createBinaryProfile()") ConditionProfile incompleteProfile, + @Cached("createEqualityProfile()") PrimitiveValueProfile baseProfile) { int[] data = new int[vec.getLength()]; - boolean complete = RDataFactory.COMPLETE_VECTOR; + boolean complete = true; for (int i = 0; i < data.length; i++) { - int dataValue = RRuntime.INT_NA; - try { - String s = vec.getDataAt(i); - if (s.length() == 0) { - complete = RDataFactory.INCOMPLETE_VECTOR; + int dataValue; + String s = vec.getDataAt(i); + if (emptyProfile.profile(s.length() == 0)) { + dataValue = RRuntime.INT_NA; + } else { + boolean negate = false; + int pos = 0; + if (s.charAt(pos) == '+') { + // skip "+" + pos++; + } else if (s.charAt(pos) == '-') { + negate = true; + pos++; + } + int base = baseArg; + if (pos < s.length() && s.charAt(pos) == '0') { + // skip "0" + pos++; + if (pos < s.length() && (s.charAt(pos) == 'x' || s.charAt(pos) == 'X')) { + if (baseZeroProfile.profile(base == 0)) { + base = 16; + } + // skip "x" or "X" + pos++; + } else { + if (baseZeroProfile.profile(base == 0)) { + base = 8; + } + // go back (to parse the "0") + pos--; + } + } else { + if (baseZeroProfile.profile(base == 0)) { + base = 10; + } + } + base = baseProfile.profile(base); + if (pos == s.length()) { + // produce NA is no data is available + dataValue = RRuntime.INT_NA; } else { - if (base == 0) { - char ch0 = s.charAt(0); - if (ch0 == '0') { - if (s.length() > 1 && (s.charAt(1) == 'x' || s.charAt(1) == 'X')) { - base = 16; + dataValue = 0; + while (pos < s.length()) { + char c = s.charAt(pos++); + int digit; + if (base > 10) { + if (c >= '0' && c <= '9') { + digit = c - '0'; + } else if (c >= 'a' && c < ('a' + base - 10)) { + digit = c - 'a' + 10; + } else if (c >= 'A' && c < ('A' + base - 10)) { + digit = c - 'A' + 10; } else { - base = 8; + dataValue = RRuntime.INT_NA; + break; } } else { - base = 10; + if (c >= '0' && c < ('0' + base)) { + digit = c - '0'; + } else { + dataValue = RRuntime.INT_NA; + break; + } + } + try { + dataValue = ExactMath.addExact(ExactMath.multiplyExact(dataValue, base), digit); + } catch (ArithmeticException e) { + dataValue = RRuntime.INT_NA; + break; } } - long value = RFFIFactory.getRFFI().getBaseRFFI().strtol(s, base); - if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) { - complete = RDataFactory.INCOMPLETE_VECTOR; - } else { - dataValue = (int) value; - } } - } catch (IllegalArgumentException ex) { - complete = RDataFactory.INCOMPLETE_VECTOR; + if (negateProfile.profile(negate)) { + // relies on -INT_NA == INT_NA + dataValue = -dataValue; + } + if (incompleteProfile.profile(dataValue == RRuntime.INT_NA)) { + complete = false; + } + data[i] = dataValue; } - data[i] = dataValue; } return RDataFactory.createIntVector(data, complete); } 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 f7fe84aa1e73285af79cd08a77842cf3f4f1eb9d..fa27e232c3ef00046c3744d4419b77e1c5e39332 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,19 +12,24 @@ */ 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.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; +import java.util.function.BiFunction; + +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.Cached; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.base.ToLowerOrUpper.StringMapNode; 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.RAttributeProfiles; -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; @@ -32,52 +37,43 @@ 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 { - private RAttributeProfiles attrProfiles = RAttributeProfiles.create(); - @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1); + casts.arg("x").defaultError(Message.REQUIRES_CHAR_VECTOR, "strtrim()").mustBe(stringValue()).asStringVector(true, true, true); + casts.arg("width").asIntegerVector(); } @Specialization - protected RStringVector srtrim(RAbstractStringVector x, RAbstractIntVector width) { + protected RStringVector srtrim(RAbstractStringVector x, RAbstractIntVector width, + @Cached("create()") StringMapNode mapNode, + @Cached("createBinaryProfile()") ConditionProfile fitsProfile) { int len = x.getLength(); int nw = width.getLength(); if (nw == 0 || nw < len && (len % nw != 0)) { + CompilerDirectives.transferToInterpreter(); throw RError.error(this, RError.Message.INVALID_ARGUMENT, "width"); } for (int i = 0; i < nw; i++) { - int widthi = width.getDataAt(i); - if (widthi == RRuntime.INT_NA || widthi < 0) { + 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"); } } - String[] data = new String[len]; - boolean complete = RDataFactory.COMPLETE_VECTOR; - for (int i = 0; i < len; i++) { - String element = x.getDataAt(i); - if (RRuntime.isNA(element)) { - data[i] = element; - complete = RDataFactory.INCOMPLETE_VECTOR; - continue; - } + BiFunction<String, Integer, String> function = (element, i) -> { // TODO multibyte character handling int w = width.getDataAt(i % nw); - if (w > element.length()) { - data[i] = element; + if (fitsProfile.profile(w >= element.length())) { + return element; } else { - data[i] = element.substring(0, w); + return substring(element, w); } - } - RStringVector result = RDataFactory.createStringVector(data, complete); - result.copyAttributesFrom(attrProfiles, x); - return result; + }; + return mapNode.apply(x, function); } - @SuppressWarnings("unused") - @Fallback @TruffleBoundary - RStringVector strtrim(Object x, Object width) { - throw RError.error(this, RError.Message.REQUIRES_CHAR_VECTOR, "strtrim()"); + private static String substring(String element, int w) { + return element.substring(0, w); } } 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 9fa98073c8dea0ec9ce5f7b26fc42f1c4efd0405..1534d7291a98160f46ab5560cf6b0ea340cb7f0e 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 @@ -96,6 +96,6 @@ public abstract class Substitute extends RBuiltinNode { // The "expr" promise comes from the no-evalarg aspect of the builtin, // so get the actual expression (AST) from that - return RASTUtils.createLanguageElement(RSubstitute.substitute(env, expr.getRep()).asRNode()); + return RASTUtils.createLanguageElement(RSubstitute.substitute(env, expr.getRep())); } } 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 c2ad959b6031e5fc4b0781633a844dd8cb96f458..b356056c0a2f2ea07c6f8653f6728bbcce4b6116 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 @@ -22,21 +22,29 @@ */ 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.RDispatch.SUMMARY_GROUP_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.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.LoopConditionProfile; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; import com.oracle.truffle.r.nodes.unary.UnaryArithmeticReduceNode; import com.oracle.truffle.r.nodes.unary.UnaryArithmeticReduceNode.ReduceSemantics; import com.oracle.truffle.r.nodes.unary.UnaryArithmeticReduceNodeGen; +import com.oracle.truffle.r.runtime.FastROptions; 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.ops.BinaryArithmetic; +import com.oracle.truffle.r.runtime.ops.na.NACheck; /** * Sum has combine semantics (TBD: exactly?) and uses a reduce operation on the resulting array. @@ -44,13 +52,15 @@ import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; @RBuiltin(name = "sum", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE) public abstract class Sum extends RBuiltinNode { + protected static final boolean FULL_PRECISION = FastROptions.FullPrecisionSum.getBooleanValue(); + private static final ReduceSemantics semantics = new ReduceSemantics(0, 0.0, true, null, null, true, false); @Child private UnaryArithmeticReduceNode reduce = UnaryArithmeticReduceNodeGen.create(semantics, BinaryArithmetic.ADD); @Override protected void createCasts(CastBuilder casts) { - casts.firstBoolean(1); + casts.arg("na.rm").allowNull().asLogicalVector().findFirst().map(toBoolean()); } @Override @@ -58,12 +68,46 @@ public abstract class Sum extends RBuiltinNode { return new Object[]{RArgsValuesAndNames.EMPTY, RRuntime.LOGICAL_FALSE}; } - @Specialization(guards = "args.getLength() == 1") + protected static boolean isRDoubleVector(Object value) { + return value instanceof RDoubleVector; + } + + @Specialization(guards = {"FULL_PRECISION", "args.getLength() == 1", "isRDoubleVector(args.getArgument(0))", "naRm == cachedNaRm"}) + protected double sumLengthOneRDoubleVector(RArgsValuesAndNames args, @SuppressWarnings("unused") boolean naRm, + @Cached("naRm") boolean cachedNaRm, + @Cached("create()") VectorLengthProfile lengthProfile, + @Cached("createCountingProfile()") LoopConditionProfile loopProfile, + @Cached("create()") NACheck na, + @Cached("createBinaryProfile()") ConditionProfile needsExactSumProfile) { + 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); + } else { + na.enable(vector); + loopProfile.profileCounted(length); + double sum = 0; + for (int i = 0; loopProfile.inject(i < length); i++) { + double value = vector.getDataAt(i); + if (na.check(value)) { + if (!cachedNaRm) { + return RRuntime.DOUBLE_NA; + } + } else { + sum += value; + } + } + return sum; + } + } + + @Specialization(contains = "sumLengthOneRDoubleVector", guards = "args.getLength() == 1") protected Object sumLengthOne(RArgsValuesAndNames args, boolean naRm) { return reduce.executeReduce(args.getArgument(0), naRm, false); } - @Specialization(contains = "sumLengthOne") + @Specialization(contains = {"sumLengthOneRDoubleVector", "sumLengthOne"}) protected Object sum(RArgsValuesAndNames args, boolean naRm, // @Cached("create()") Combine combine) { return reduce.executeReduce(combine.executeCombine(args), naRm, false); 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 a787025f2617d7a6391e07ee7ebdecd662bc5ad3..c41df4be78fcdfafbb4cb032d0a9a36ee8effe05 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 @@ -23,13 +23,13 @@ import com.oracle.truffle.api.profiles.ConditionProfile; 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.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.RMissing; import com.oracle.truffle.r.runtime.data.RNull; @@ -46,8 +46,10 @@ 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 { + @Child private CastIntegerNode castIntNode; @Child private PromiseCheckHelperNode promiseHelper = new PromiseCheckHelperNode(); + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); private final BranchProfile suppliedArgNameIsEmpty = BranchProfile.create(); private final BranchProfile suppliedArgNameIsNull = BranchProfile.create(); @@ -61,7 +63,7 @@ public abstract class Switch extends RBuiltinNode { if (x.getLength() != 1) { throw RError.error(this, RError.Message.EXPR_NOT_LENGTH_ONE); } - return prepareResult(doSwitchString(frame, x, optionalArgs)); + return prepareResult(frame, doSwitchString(frame, x, optionalArgs)); } private Object doSwitchString(VirtualFrame frame, RAbstractStringVector x, RArgsValuesAndNames optionalArgs) { @@ -130,7 +132,7 @@ public abstract class Switch extends RBuiltinNode { @Specialization protected Object doSwitch(VirtualFrame frame, int x, RArgsValuesAndNames optionalArgs) { - return prepareResult(doSwitchInt(frame, x, optionalArgs)); + return prepareResult(frame, doSwitchInt(frame, x, optionalArgs)); } @Specialization @@ -144,7 +146,7 @@ public abstract class Switch extends RBuiltinNode { notIntType.enter(); return null; } - return prepareResult(doSwitchInt(frame, (int) objIndex, optionalArgs)); + return prepareResult(frame, doSwitchInt(frame, (int) objIndex, optionalArgs)); } @SuppressWarnings("unused") @@ -166,12 +168,12 @@ public abstract class Switch extends RBuiltinNode { return null; } - private Object prepareResult(Object value) { + private Object prepareResult(VirtualFrame frame, Object value) { if (returnValueProfile.profile(value != null)) { - RContext.getInstance().setVisible(true); + visibility.execute(frame, true); return value; } else { - RContext.getInstance().setVisible(false); + visibility.execute(frame, false); return RNull.instance; } } 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 c9ec3cf691058f7a0c9b720677fd0a57c8dd58b9..b020cfb2189514bbc70feaadb3186a4504db4033 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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; @@ -31,16 +32,21 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.attribute.FileTime; import java.util.ArrayList; import java.util.Map; +import java.util.concurrent.TimeUnit; -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.Frame; import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; +import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinPackages; import com.oracle.truffle.r.runtime.RArguments; @@ -64,7 +70,6 @@ public class SysFunctions { @RBuiltin(name = "Sys.getpid", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) public abstract static class SysGetpid extends RBuiltinNode { - @Specialization @TruffleBoundary protected Object sysGetPid() { @@ -77,9 +82,15 @@ public class SysFunctions { public abstract static class SysGetenv extends RBuiltinNode { private final ConditionProfile zeroLengthProfile = ConditionProfile.createBinaryProfile(); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(stringValue(), RError.Message.ARGUMENT_WRONG_TYPE); + casts.arg("unset").mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst(); + } + @Specialization @TruffleBoundary - protected Object sysGetEnv(RAbstractStringVector x, RAbstractStringVector unset) { + protected Object sysGetEnv(RAbstractStringVector x, String unset) { Map<String, String> envMap = RContext.getInstance().stateREnvVars.getMap(); int len = x.getLength(); if (zeroLengthProfile.profile(len == 0)) { @@ -100,8 +111,8 @@ public class SysFunctions { if (value != null) { data[i] = value; } else { - data[i] = unset.getDataAt(0); - if (RRuntime.isNA(unset.getDataAt(0))) { + data[i] = unset; + if (RRuntime.isNA(unset)) { complete = RDataFactory.INCOMPLETE_VECTOR; } } @@ -110,11 +121,6 @@ public class SysFunctions { } } - @Specialization - protected Object sysGetEnvGeneric(@SuppressWarnings("unused") Object x, @SuppressWarnings("unused") Object unset) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.WRONG_TYPE); - } } /** @@ -129,16 +135,20 @@ public class SysFunctions { protected void checkNSLoad(VirtualFrame frame, RAbstractStringVector names, RAbstractStringVector values, boolean setting) { if (names.getLength() == 1 && NS_LOAD.equals(names.getDataAt(0))) { - 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()); - } - System.console(); + 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()); } } @@ -147,9 +157,17 @@ public class SysFunctions { @RBuiltin(name = "Sys.setenv", visibility = OFF, kind = INTERNAL, parameterNames = {"nm", "values"}, behavior = MODIFIES_STATE) public abstract static class SysSetEnv extends LoadNamespaceAdapter { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("nm").mustBe(stringValue(), RError.Message.ARGUMENT_WRONG_TYPE); + casts.arg("values").mustBe(stringValue(), RError.Message.ARGUMENT_WRONG_TYPE); + } @Specialization protected RLogicalVector doSysSetEnv(VirtualFrame frame, RAbstractStringVector names, RAbstractStringVector values) { + if (names.getLength() != values.getLength()) { + throw RError.error(this, RError.Message.ARGUMENT_WRONG_LENGTH); + } checkNSLoad(frame, names, values, true); return doSysSetEnv(names, values); } @@ -168,6 +186,10 @@ public class SysFunctions { @RBuiltin(name = "Sys.unsetenv", visibility = OFF, kind = INTERNAL, parameterNames = {"x"}, behavior = READS_STATE) public abstract static class SysUnSetEnv extends LoadNamespaceAdapter { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(stringValue(), RError.Message.ARGUMENT_WRONG_TYPE); + } @Specialization protected RLogicalVector doSysUnSetEnv(VirtualFrame frame, RAbstractStringVector names) { @@ -189,6 +211,10 @@ public class SysFunctions { @RBuiltin(name = "Sys.sleep", visibility = OFF, kind = INTERNAL, parameterNames = {"time"}, behavior = COMPLEX) public abstract static class SysSleep extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("time").asDoubleVector().findFirst().mustBe(gte(0.0).and(eq(Double.NaN).not())); + } @Specialization @TruffleBoundary @@ -197,44 +223,10 @@ public class SysFunctions { return RNull.instance; } - @Specialization - @TruffleBoundary - protected Object sysSleep(String secondsString) { - long millis = convertToMillis(checkValidString(secondsString)); - sleep(millis); - return RNull.instance; - } - - @Specialization(guards = "lengthOne(secondsVector)") - @TruffleBoundary - protected Object sysSleep(RStringVector secondsVector) { - long millis = convertToMillis(checkValidString(secondsVector.getDataAt(0))); - sleep(millis); - return RNull.instance; - } - - protected static boolean lengthOne(RStringVector vec) { - return vec.getLength() == 1; - } - - @Specialization - @TruffleBoundary - protected Object sysSleep(@SuppressWarnings("unused") Object arg) { - throw RError.error(this, RError.Message.INVALID_VALUE, "time"); - } - private static long convertToMillis(double d) { return (long) (d * 1000); } - private double checkValidString(String s) { - try { - return Double.parseDouble(s); - } catch (NumberFormatException ex) { - throw RError.error(this, RError.Message.INVALID_VALUE, "time"); - } - } - private static void sleep(long millis) { try { Thread.sleep(millis); @@ -249,16 +241,14 @@ public class SysFunctions { */ @RBuiltin(name = "Sys.readlink", kind = INTERNAL, parameterNames = {"paths"}, behavior = IO) public abstract static class SysReadlink extends RBuiltinNode { - - @Specialization - @TruffleBoundary - protected Object sysReadlink(String path) { - return RDataFactory.createStringVector(doSysReadLink(path)); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("paths").mustBe(stringValue()); } @Specialization @TruffleBoundary - protected Object sysReadlink(RStringVector vector) { + protected Object sysReadlink(RAbstractStringVector vector) { String[] paths = new String[vector.getLength()]; boolean complete = RDataFactory.COMPLETE_VECTOR; for (int i = 0; i < paths.length; i++) { @@ -289,19 +279,20 @@ public class SysFunctions { return s; } - @Specialization - protected Object sysReadlinkGeneric(@SuppressWarnings("unused") Object path) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "paths"); - } } - // TODO implement @RBuiltin(name = "Sys.chmod", visibility = OFF, kind = INTERNAL, parameterNames = {"paths", "octmode", "use_umask"}, behavior = IO) public abstract static class SysChmod extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + 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()); + } + @Specialization @TruffleBoundary - protected RLogicalVector sysChmod(RAbstractStringVector pathVec, RAbstractIntVector octmode, @SuppressWarnings("unused") byte useUmask) { + protected RLogicalVector sysChmod(RAbstractStringVector pathVec, RAbstractIntVector octmode, @SuppressWarnings("unused") boolean useUmask) { byte[] data = new byte[pathVec.getLength()]; for (int i = 0; i < data.length; i++) { String path = Utils.tildeExpand(pathVec.getDataAt(i)); @@ -318,10 +309,15 @@ public class SysFunctions { // TODO implement @RBuiltin(name = "Sys.umask", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"octmode"}, behavior = COMPLEX) public abstract static class SysUmask extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("octmode").asIntegerVector().findFirst(); + } + @SuppressWarnings("unused") @Specialization @TruffleBoundary - protected Object sysChmod(Object octmode) { + protected Object sysUmask(int octmode) { throw RError.nyi(this, "Sys.umask"); } } @@ -361,10 +357,15 @@ public class SysFunctions { @RBuiltin(name = "Sys.glob", kind = INTERNAL, parameterNames = {"paths", "dirmask"}, behavior = IO) public abstract static class SysGlob extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("paths").mustBe(stringValue()).asStringVector(); + casts.arg("dirmask").asLogicalVector().findFirst().notNA().map(toBoolean()); + } @Specialization @TruffleBoundary - protected Object sysGlob(RAbstractStringVector pathVec, @SuppressWarnings("unused") byte dirMask) { + protected Object sysGlob(RAbstractStringVector pathVec, @SuppressWarnings("unused") boolean dirMask) { ArrayList<String> matches = new ArrayList<>(); // Sys.glob closure already called path.expand for (int i = 0; i < pathVec.getLength(); i++) { @@ -380,4 +381,24 @@ public class SysFunctions { return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR); } } + + @RBuiltin(name = "setFileTime", kind = INTERNAL, parameterNames = {"path", "time"}, behavior = IO) + public abstract static class SysSetFileTime extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("path").mustBe(stringValue()).asStringVector().findFirst(); + casts.arg("time").asIntegerVector().findFirst().notNA(); + } + + @Specialization + @TruffleBoundary + protected byte sysSetFileTime(String path, int time) { + try { + Files.setLastModifiedTime(FileSystems.getDefault().getPath(path), FileTime.from(time, TimeUnit.SECONDS)); + return RRuntime.LOGICAL_TRUE; + } catch (IOException ex) { + return RRuntime.LOGICAL_FALSE; + } + } + } } 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 d690fced48fa9dd4ebf4d1442f664e27ca4ec12e..9accf74b28f744b5102b80960a6d1a4a85231668 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 @@ -10,13 +10,11 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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.TruffleBoundary; -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.LoopConditionProfile; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; @@ -30,20 +28,16 @@ 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 { - private final BranchProfile errorProfile = BranchProfile.create(); private final LoopConditionProfile loopProfile = LoopConditionProfile.createCountingProfile(); @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1); + 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)); } @Specialization protected RIntVector tabulate(RAbstractIntVector bin, int nBins) { - if (RRuntime.isNA(nBins) || nBins < 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "nbin"); - } int[] ans = new int[nBins]; loopProfile.profileCounted(bin.getLength()); for (int i = 0; loopProfile.inject(i < bin.getLength()); i++) { @@ -55,10 +49,4 @@ public abstract class Tabulate extends RBuiltinNode { return RDataFactory.createIntVector(ans, RDataFactory.COMPLETE_VECTOR); } - @SuppressWarnings("unused") - @Fallback - @TruffleBoundary - protected RIntVector tabulate(Object bin, int nBins) { - throw RError.error(this, RError.Message.INVALID_INPUT); - } } 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 d3318f5e976edf3e976ab543851e46e675dbb1af..070b089bb2f517578e02568d65fdd2e010ac6a42 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 @@ -22,15 +22,17 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; -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.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.TempPathName; +import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RStringVector; @@ -38,91 +40,29 @@ 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 { - @CompilationFinal private int stringVectorsAmount; - private static final String INVALID_PATTERN = mkErrorMsg("filename"); - private static final String INVALID_TEMPDIR = mkErrorMsg("tempdir"); - private static final String INVALID_FILEEXT = mkErrorMsg("file extension"); - - private static String mkErrorMsg(String msg) { - return "invalid '" + msg + "'"; + @Override + protected void createCasts(CastBuilder casts) { + 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"); } - @Specialization(guards = "tempDir.getLength() == 1") @TruffleBoundary - protected RStringVector tempfile(String pattern, RAbstractStringVector tempDir, String fileExt) { - return RDataFactory.createStringVector(TempPathName.createNonExistingFilePath(pattern, tempDir.getDataAt(0), fileExt)); - } - @Specialization - @TruffleBoundary - protected RStringVector tempfileGeneric(Object pattern, Object tempDir, Object fileExt) { - // Now we have RStringVectors of at least length 1 - RStringVector[] argVecs = new RStringVector[]{checkVector(pattern, INVALID_PATTERN), checkVector(tempDir, INVALID_TEMPDIR), checkVector(fileExt, INVALID_FILEEXT)}; - stringVectorsAmount = argVecs.length; - int maxL = findMaxLengthIn(argVecs); - extendVectorsToSameLength(argVecs, maxL); // Now all vectors are same length - return RDataFactory.createStringVector(createTempFilesPaths(argVecs, maxL), true); - } - - @TruffleBoundary - private int findMaxLengthIn(RStringVector[] stringVectors) { - int maxLength = 0; - for (int i = 0; i < stringVectorsAmount; i++) { - int length = stringVectors[i].getLength(); - if (length > maxLength) { - maxLength = length; - } - } - return maxLength; - } - - @TruffleBoundary - private void extendVectorsToSameLength(RStringVector[] stringVectors, int desiredLength) { - for (int i = 0; i < stringVectorsAmount; i++) { - RStringVector stringVector = stringVectors[i]; - int length = stringVector.getLength(); - if (length < desiredLength) { - stringVectors[i] = extendVector(stringVector, length, desiredLength); - } + protected RStringVector tempfile(RAbstractStringVector pattern, String tempDir, RAbstractStringVector fileExt) { + int patternLength = pattern.getLength(); + int fileExtLength = fileExt.getLength(); + int maxLength = Math.max(patternLength, fileExtLength); + String[] data = new String[maxLength]; + int patternInd = 0; + int fileExtInd = 0; + for (int i = 0; i < maxLength; i++) { + data[i] = TempPathName.createNonExistingFilePath(pattern.getDataAt(patternInd), tempDir, fileExt.getDataAt(fileExtInd)); + patternInd = Utils.incMod(patternInd, patternLength); + fileExtInd = Utils.incMod(fileExtInd, fileExtLength); } + return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR); } - @TruffleBoundary - private static RStringVector extendVector(RStringVector vec, int vecL, int maxL) { - String[] data = new String[maxL]; - int i = 0; - while (i < vecL) { - data[i] = vec.getDataAt(i); - i++; - } - while (i < maxL) { - data[i] = vec.getDataAt(i % vecL); - i++; - } - return RDataFactory.createStringVector(data, true); - } - - @TruffleBoundary - private static String[] createTempFilesPaths(RStringVector[] stringVectors, int pathsAmount) { - // pathsAmount must be equals to length of vector. All vectors must be same length - String[] paths = new String[pathsAmount]; - for (int i = 0; i < pathsAmount; i++) { - paths[i] = TempPathName.createNonExistingFilePath(stringVectors[0].getDataAt(i), stringVectors[1].getDataAt(i), stringVectors[2].getDataAt(i)); - } - return paths; - } - - @TruffleBoundary - private RStringVector checkVector(Object obj, String msg) { - if (obj instanceof RStringVector) { - RStringVector result = (RStringVector) obj; - if (result.getLength() > 0) { - return result; - } - } else if (obj instanceof String) { - return RDataFactory.createStringVector((String) obj); - } - throw RError.error(this, RError.Message.GENERIC, msg); - } } 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 d12bcadb18d22e87bd27a4b3046fe3b117c3aeb4..0313cad4b98aec16177b01b33fe7021ffa3fa6ee 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 @@ -22,73 +22,121 @@ */ 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.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; +import java.util.function.BiFunction; + 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.LoopConditionProfile; import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNode; +import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNodeGen; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RAttributeProfiles; 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; -import com.oracle.truffle.r.runtime.nodes.RNode; +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; -public abstract class ToLowerOrUpper extends RBuiltinNode { +public abstract class ToLowerOrUpper { - @RBuiltin(name = "tolower", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) - public static final class ToLower { - } + public static final class StringMapNode extends RBaseNode { - @RBuiltin(name = "toupper", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) - public static final class ToUpper { - } + private final VectorLengthProfile lengthProfile = VectorLengthProfile.create(); + private final LoopConditionProfile loopProfile = LoopConditionProfile.createCountingProfile(); + private final NACheck na = NACheck.create(); + private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); - public static ToLowerOrUpper createToLower(RNode[] arguments) { - return ToLowerOrUpperNodeGen.create(true, arguments); - } + @Child private CopyOfRegAttributesNode copyAttributes = CopyOfRegAttributesNodeGen.create(); - public static ToLowerOrUpper createToUpper(RNode[] arguments) { - return ToLowerOrUpperNodeGen.create(false, arguments); - } + private StringMapNode() { + // nothing to do + } - private final boolean lower; + public static StringMapNode create() { + return new StringMapNode(); + } - public ToLowerOrUpper(boolean lower) { - this.lower = lower; - } + private String elementFunction(String value, int i, BiFunction<String, Integer, String> function) { + return na.check(value) ? RRuntime.STRING_NA : function.apply(value, i); + } + + public String apply(String value, BiFunction<String, Integer, String> function) { + na.enable(value); + return elementFunction(value, 0, function); + } - @TruffleBoundary - private String processElement(String value) { - return lower ? value.toLowerCase() : value.toUpperCase(); + public RStringVector apply(RAbstractStringVector vector, BiFunction<String, Integer, String> function) { + na.enable(vector); + int length = lengthProfile.profile(vector.getLength()); + String[] stringVector = new String[length]; + loopProfile.profileCounted(length); + for (int i = 0; loopProfile.inject(i < length); i++) { + String value = vector.getDataAt(i); + stringVector[i] = elementFunction(value, i, function); + } + RStringVector result = RDataFactory.createStringVector(stringVector, vector.isComplete(), vector.getDimensions(), vector.getNames(attrProfiles)); + copyAttributes.execute(vector, result); + return result; + } } - @Specialization - protected String toLower(String value, // - @Cached("create()") NAProfile na) { - return na.isNA(value) ? RRuntime.STRING_NA : processElement(value); + @RBuiltin(name = "tolower", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) + public abstract static class ToLower extends RBuiltinNode { + + @Child private StringMapNode mapNode = StringMapNode.create(); + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg(0, "x").mustBe(stringValue()).asStringVector(true, true, true); + } + + @TruffleBoundary + private static String processElement(String value, @SuppressWarnings("unused") int i) { + return value.toLowerCase(); + } + + @Specialization + protected String toLower(String value) { + return mapNode.apply(value, ToLower::processElement); + } + + @Specialization + protected RStringVector toLower(RAbstractStringVector vector) { + return mapNode.apply(vector, ToLower::processElement); + } } - @Specialization - protected RStringVector toLower(RAbstractStringVector vector, // - @Cached("createCountingProfile()") LoopConditionProfile loopProfile, // - @Cached("create()") NACheck na, // - @Cached("create()") CopyOfRegAttributesNode copyAttributes) { - na.enable(vector); - String[] stringVector = new String[vector.getLength()]; - loopProfile.profileCounted(vector.getLength()); - for (int i = 0; loopProfile.inject(i < vector.getLength()); i++) { - String value = vector.getDataAt(i); - stringVector[i] = na.check(value) ? RRuntime.STRING_NA : processElement(value); + @RBuiltin(name = "toupper", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) + public abstract static class ToUpper extends RBuiltinNode { + + @Child private StringMapNode mapNode = StringMapNode.create(); + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg(0, "x").mustBe(stringValue()).asStringVector(true, true, true); + } + + @TruffleBoundary + private static String processElement(String value, @SuppressWarnings("unused") int i) { + return value.toUpperCase(); + } + + @Specialization + protected String toLower(String value) { + return mapNode.apply(value, ToUpper::processElement); + } + + @Specialization + protected RStringVector toLower(RAbstractStringVector vector) { + return mapNode.apply(vector, ToUpper::processElement); } - RStringVector result = RDataFactory.createStringVector(stringVector, vector.isComplete(), vector.getDimensions()); - copyAttributes.execute(vector, result); - return result; } } 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 d294b653a4db4d9fc01226325f0dca790b9db417..cea9add9c88601c0c8c330c7c39105bdfb09d357 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 @@ -22,9 +22,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.nullValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asStringVector; +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; @@ -45,6 +48,7 @@ import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RError; @@ -54,7 +58,7 @@ import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.conn.StdConnections; import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.MemoryTracer; +import com.oracle.truffle.r.runtime.data.MemoryCopyTracer; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; @@ -63,9 +67,17 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; public class TraceFunctions { - private abstract static class Helper extends RBuiltinNode { + private abstract static class PrimTraceAdapter extends RBuiltinNode { @Child private GetFunctions.Get getNode; + @Override + protected void createCasts(CastBuilder casts) { + // @formatter:off + casts.arg("what").mustBe(instanceOf(RFunction.class).or(stringValue()), SHOW_CALLER, Message.ARG_MUST_BE_FUNCTION). + mapIf(stringValue(), chain(asStringVector()).with(findFirst().stringElement()).end()); + // @formatter:on + } + protected Object getFunction(VirtualFrame frame, String funcName) { if (getNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -76,10 +88,10 @@ public class TraceFunctions { } @RBuiltin(name = ".primTrace", visibility = OFF, kind = PRIMITIVE, parameterNames = "what", behavior = COMPLEX) - public abstract static class PrimTrace extends Helper { + public abstract static class PrimTrace extends PrimTraceAdapter { @Specialization - protected RNull primUnTrace(VirtualFrame frame, RAbstractStringVector funcName) { + protected RNull primTrace(VirtualFrame frame, RAbstractStringVector funcName) { return primTrace((RFunction) getFunction(frame, funcName.getDataAt(0))); } @@ -96,7 +108,7 @@ public class TraceFunctions { } @RBuiltin(name = ".primUntrace", visibility = OFF, kind = PRIMITIVE, parameterNames = "what", behavior = COMPLEX) - public abstract static class PrimUnTrace extends Helper { + public abstract static class PrimUnTrace extends PrimTraceAdapter { @Specialization protected RNull primUnTrace(VirtualFrame frame, RAbstractStringVector funcName) { @@ -118,10 +130,12 @@ public class TraceFunctions { @Specialization @TruffleBoundary protected byte traceOnOff(byte state) { + /* TODO GnuR appears to accept ANY value as an argument */ boolean prevState = RContext.getInstance().stateInstrumentation.getTracingState(); boolean newState = RRuntime.fromLogical(state); if (newState != prevState) { RContext.getInstance().stateInstrumentation.setTracingState(newState); + MemoryCopyTracer.setTracingState(newState); } return RRuntime.asLogical(prevState); } @@ -135,22 +149,34 @@ public class TraceFunctions { public abstract static class TracememBase extends RBuiltinNode { static { - MemoryTracer.setListener(new TracememBase.TracememListener()); + MemoryCopyTracer.addListener(new TracememBase.TracememListener()); } + @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 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); - MemoryTracer.reportEvents(); + boolean tracingState = RContext.getInstance().stateInstrumentation.getTracingState(); + if (tracingState) { + MemoryCopyTracer.setTracingState(true); + } } + @TruffleBoundary protected static void printToStdout(String msg) { try { StdConnections.getStdout().writeString(msg, true); @@ -176,7 +202,8 @@ public class TraceFunctions { return result.toString(); } - private static final class TracememListener implements MemoryTracer.Listener { + private static final class TracememListener implements MemoryCopyTracer.Listener { + @TruffleBoundary @Override public void reportCopying(RAbstractVector src, RAbstractVector dest) { if (getTracedObjects().contains(src)) { @@ -195,7 +222,7 @@ public class TraceFunctions { public abstract static class Tracemem extends TracememBase { @Override protected void createCasts(CastBuilder casts) { - casts.arg("x").mustBe(nullValue().not(), Message.TRACEMEM_NOT_NULL); + casts.arg("x").mustNotBeNull(Message.TRACEMEM_NOT_NULL); } @Specialization @@ -212,24 +239,28 @@ public class TraceFunctions { */ @RBuiltin(name = "retracemem", kind = PRIMITIVE, visibility = CUSTOM, parameterNames = {"x", "previous"}, behavior = COMPLEX) public abstract static class Retracemem extends TracememBase { + + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); + @Override protected void createCasts(CastBuilder casts) { - casts.arg("previous").defaultError(Message.INVALID_ARGUMENT, "previous").mustBe(stringValue().or(missingValue())); + casts.arg("previous").defaultError(Message.INVALID_ARGUMENT, "previous").allowNullAndMissing().mustBe(stringValue()); } @Specialization - protected Object execute(Object x, @SuppressWarnings("unused") RNull previous) { - return getResult(x); + protected Object execute(VirtualFrame frame, Object x, @SuppressWarnings("unused") RNull previous) { + return getResult(frame, x); } @Specialization - protected Object execute(Object x, @SuppressWarnings("unused") RMissing previous) { - return getResult(x); + protected Object execute(VirtualFrame frame, Object x, @SuppressWarnings("unused") RMissing previous) { + return getResult(frame, x); } @Specialization - protected Object execute(Object x, String previous) { - Object result = getResult(x); + protected Object execute(VirtualFrame frame, Object x, String previous) { + CompilerDirectives.transferToInterpreter(); + Object result = getResult(frame, x); if (x != null && x != RNull.instance) { startTracing(x); printToStdout(String.format("tracemem[%s -> 0x%x]: %s", previous, x.hashCode(), getStackTrace())); @@ -237,12 +268,12 @@ public class TraceFunctions { return result; } - private static Object getResult(Object x) { + private Object getResult(VirtualFrame frame, Object x) { if (!isRNull(x) && getTracedObjects().contains(x)) { - RContext.getInstance().setVisible(true); + visibility.execute(frame, true); return formatHashCode(x); } else { - RContext.getInstance().setVisible(false); + visibility.execute(frame, false); return RNull.instance; } } @@ -251,6 +282,7 @@ public class TraceFunctions { @RBuiltin(name = "untracemem", kind = PRIMITIVE, visibility = OFF, parameterNames = "x", behavior = COMPLEX) public abstract static class Untracemem extends TracememBase { @Specialization + @TruffleBoundary protected RNull execute(Object x) { getTracedObjects().remove(x); return RNull.instance; 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 7512b96c602e04cc9c48d22d6d5da86745e7cbb5..fca379d84142ae6ae0350162429fc636a0f311ba 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 @@ -22,6 +22,7 @@ */ 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.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -37,7 +38,7 @@ public abstract class Traceback extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.firstIntegerWithWarning(0, 0, "x"); + casts.arg("x").mustBe(numericValue()).asIntegerVector().findFirst(); } @Specialization 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 c1a394c20d9e60501af8df2d9a4d7e1e24272140..b31b88e2a07d514e25968d47ad9336e7a096e2e3 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 @@ -13,88 +13,86 @@ 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.SUBSTITUTE; +import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; +import java.util.function.BiFunction; +import java.util.function.Function; + +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.api.profiles.LoopConditionProfile; import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNode; import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNodeGen; import com.oracle.truffle.r.nodes.attributes.InitAttributesNode; import com.oracle.truffle.r.nodes.attributes.PutAttributeNode; import com.oracle.truffle.r.nodes.attributes.PutAttributeNodeGen; 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.RAttributeProfiles; +import com.oracle.truffle.r.runtime.data.RComplex; 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.RVector; +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; import com.oracle.truffle.r.runtime.nodes.RNode; -@RBuiltin(name = "t.default", kind = SUBSTITUTE, parameterNames = {"x"}, behavior = PURE) -// TODO INTERNAL +@RBuiltin(name = "t.default", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) public abstract class Transpose extends RBuiltinNode { private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); private final BranchProfile hasDimNamesProfile = BranchProfile.create(); private final ConditionProfile isMatrixProfile = ConditionProfile.createBinaryProfile(); + private final VectorLengthProfile lengthProfile = VectorLengthProfile.create(); + private final LoopConditionProfile loopProfile = LoopConditionProfile.createCountingProfile(); + @Child private CopyOfRegAttributesNode copyRegAttributes = CopyOfRegAttributesNodeGen.create(); @Child private InitAttributesNode initAttributes = InitAttributesNode.create(); @Child private PutAttributeNode putDimensions = PutAttributeNodeGen.createDim(); @Child private PutAttributeNode putDimNames = PutAttributeNodeGen.createDimNames(); - public abstract Object execute(Object o); - - @Specialization - protected RNull transpose(RNull value) { - return value; - } - - @Specialization - protected int transpose(int value) { - return value; - } - - @Specialization - protected double transpose(double value) { - return value; - } - - @Specialization - protected byte transpose(byte value) { - return value; - } - - @Specialization(guards = "isEmpty2D(vector)") - protected RAbstractVector transpose(RAbstractVector vector) { - int[] dim = vector.getDimensions(); - return vector.copyWithNewDimensions(new int[]{dim[1], dim[0]}); - } + public abstract Object execute(RAbstractVector o); @FunctionalInterface - private interface InnerLoop<T extends RAbstractVector> { - RVector apply(T vector, int firstDim); + private interface WriteArray<T extends RAbstractVector, A> { + void apply(A array, T vector, int i, int j); } - protected <T extends RAbstractVector> RVector transposeInternal(T vector, InnerLoop<T> innerLoop) { + protected <T extends RAbstractVector, A> RVector<?> transposeInternal(T vector, Function<Integer, A> createArray, WriteArray<T, A> writeArray, BiFunction<A, Boolean, RVector<?>> createResult) { + int length = lengthProfile.profile(vector.getLength()); int firstDim; int secondDim; if (isMatrixProfile.profile(vector.isMatrix())) { firstDim = vector.getDimensions()[0]; secondDim = vector.getDimensions()[1]; } else { - firstDim = vector.getLength(); + firstDim = length; secondDim = 1; } - RNode.reportWork(this, vector.getLength()); + RNode.reportWork(this, length); - RVector r = innerLoop.apply(vector, firstDim); + A array = createArray.apply(length); + int j = 0; + loopProfile.profileCounted(length); + for (int i = 0; loopProfile.inject(i < length); i++, j += firstDim) { + if (j > (length - 1)) { + j -= (length - 1); + } + writeArray.apply(array, vector, i, j); + } + RVector<?> r = createResult.apply(array, vector.isComplete()); // copy attributes copyRegAttributes.execute(vector, r); // set new dimensions @@ -113,61 +111,47 @@ public abstract class Transpose extends RBuiltinNode { return r; } - private static RVector innerLoopInt(RAbstractIntVector vector, int firstDim) { - int[] result = new int[vector.getLength()]; - int j = 0; - for (int i = 0; i < result.length; i++, j += firstDim) { - if (j > (result.length - 1)) { - j -= (result.length - 1); - } - result[i] = vector.getDataAt(j); - } - return RDataFactory.createIntVector(result, vector.isComplete()); + @Specialization + protected RVector<?> transpose(RAbstractIntVector x) { + return transposeInternal(x, l -> new int[l], (a, v, i, j) -> a[i] = v.getDataAt(j), RDataFactory::createIntVector); } - private static RVector innerLoopDouble(RAbstractDoubleVector vector, int firstDim) { - double[] result = new double[vector.getLength()]; - int j = 0; - for (int i = 0; i < result.length; i++, j += firstDim) { - if (j > (result.length - 1)) { - j -= (result.length - 1); - } - result[i] = vector.getDataAt(j); - } - return RDataFactory.createDoubleVector(result, vector.isComplete()); + @Specialization + protected RVector<?> transpose(RAbstractLogicalVector x) { + return transposeInternal(x, l -> new byte[l], (a, v, i, j) -> a[i] = v.getDataAt(j), RDataFactory::createLogicalVector); } - private static RVector innerLoopString(RAbstractStringVector vector, int firstDim) { - String[] result = new String[vector.getLength()]; - int j = 0; - for (int i = 0; i < result.length; i++, j += firstDim) { - if (j > (result.length - 1)) { - j -= (result.length - 1); - } - result[i] = vector.getDataAt(j); - } - return RDataFactory.createStringVector(result, vector.isComplete()); + @Specialization + protected RVector<?> transpose(RAbstractDoubleVector x) { + return transposeInternal(x, l -> new double[l], (a, v, i, j) -> a[i] = v.getDataAt(j), RDataFactory::createDoubleVector); } - @Specialization(guards = "!isEmpty2D(vector)") - protected RVector transpose(RAbstractIntVector vector) { - return transposeInternal(vector, Transpose::innerLoopInt); + @Specialization + protected RVector<?> transpose(RAbstractComplexVector x) { + return transposeInternal(x, l -> new double[l * 2], (a, v, i, j) -> { + RComplex d = v.getDataAt(j); + a[i * 2] = d.getRealPart(); + a[i * 2 + 1] = d.getImaginaryPart(); + }, RDataFactory::createComplexVector); } - @Specialization(guards = "!isEmpty2D(vector)") - protected RVector transpose(RAbstractDoubleVector vector) { - return transposeInternal(vector, Transpose::innerLoopDouble); + @Specialization + protected RVector<?> transpose(RAbstractStringVector x) { + return transposeInternal(x, l -> new String[l], (a, v, i, j) -> a[i] = v.getDataAt(j), RDataFactory::createStringVector); } - @Specialization(guards = "!isEmpty2D(vector)") - protected RVector transpose(RAbstractStringVector vector) { - return transposeInternal(vector, Transpose::innerLoopString); + @Specialization + protected RVector<?> transpose(RAbstractListVector x) { + return transposeInternal(x, l -> new Object[l], (a, v, i, j) -> a[i] = v.getDataAt(j), (a, c) -> RDataFactory.createList(a)); } - protected static boolean isEmpty2D(RAbstractVector vector) { - if (!vector.hasDimensions()) { - return false; - } - return vector.getDimensions().length == 2 && vector.getLength() == 0; + @Specialization + protected RVector<?> transpose(RAbstractRawVector x) { + return transposeInternal(x, l -> new byte[l], (a, v, i, j) -> a[i] = v.getRawDataAt(j), (a, c) -> RDataFactory.createRawVector(a)); + } + + @Fallback + protected RVector<?> transpose(@SuppressWarnings("unused") Object x) { + throw RError.error(RError.SHOW_CALLER, 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 24e9c6925e0caa423d04fa1ddd24e5ffbe52ca96..f570ce8ddd0f819a69ca099b84a4c55456a40c1a 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 @@ -32,12 +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.profiles.BranchProfile; import com.oracle.truffle.api.profiles.LoopConditionProfile; -import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNode; -import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNodeGen; -import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode; -import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.TrigExpFunctionsFactory.AcosNodeGen; @@ -55,127 +50,14 @@ 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.RDoubleVector; -import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic.Pow.CHypot; import com.oracle.truffle.r.runtime.ops.na.NACheck; public class TrigExpFunctions { - public abstract static class TrigExpFunctionNode extends RBuiltinNode { - - @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create(); - @Child private CHypot chypot; - - @Specialization - protected Object calculateUnboxed(Object value) { - return calculate(boxPrimitive.execute(value)); - } - - protected Object calculate(@SuppressWarnings("unused") Object value) { - throw new UnsupportedOperationException(); - } - - private void ensureChypot() { - if (chypot == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - chypot = insert(new CHypot()); - } - } - - protected double hypot(double re, double im) { - ensureChypot(); - return chypot.chypot(re, im); - } - } - - public abstract static class AdapterCall1 extends RBuiltinNode { - - @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create(); - - private final BranchProfile notCompleteIntValueMet = BranchProfile.create(); - private final BranchProfile notCompleteDoubleValueMet = BranchProfile.create(); - private final NACheck na = NACheck.create(); - - @Child private UnaryCopyAttributesNode copyAttributes = UnaryCopyAttributesNodeGen.create(true); - - @Specialization - protected byte isType(@SuppressWarnings("unused") RMissing value) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.ARGUMENTS_PASSED_0_1, getRBuiltin().name()); - } - - protected double op(@SuppressWarnings("unused") double x) { - // not abstract because this would confuse the DSL annotation - // processor - throw RInternalError.shouldNotReachHere("this method needs to be implemented in subclasses"); - } - - private double doFunInt(int value) { - if (na.check(value)) { - notCompleteIntValueMet.enter(); - return RRuntime.DOUBLE_NA; - } - return op(value); - } - - private double doFunDouble(double value) { - if (na.check(value)) { - notCompleteDoubleValueMet.enter(); - return value; - } - return op(value); - } - - @Specialization - protected double trigOp(int x) { - na.enable(x); - return doFunInt(x); - } - - @Specialization - protected double trigOp(double x) { - na.enable(x); - return doFunDouble(x); - } - - @Specialization - protected RAbstractVector trigOp(RIntVector vector, // - @Cached("createCountingProfile()") LoopConditionProfile profile) { - int length = vector.getLength(); - double[] resultVector = new double[length]; - reportWork(length); - profile.profileCounted(length); - na.enable(vector); - for (int i = 0; profile.inject(i < length); i++) { - resultVector[i] = doFunInt(vector.getDataAt(i)); - } - return createDoubleVectorBasedOnOrigin(resultVector, vector); - } - - @Specialization - protected RAbstractVector trigOp(RDoubleVector vector, // - @Cached("createCountingProfile()") LoopConditionProfile profile) { - int length = vector.getLength(); - double[] resultVector = new double[length]; - reportWork(length); - profile.profileCounted(length); - na.enable(vector); - for (int i = 0; profile.inject(i < length); i++) { - resultVector[i] = doFunDouble(vector.getDataAt(i)); - } - return createDoubleVectorBasedOnOrigin(resultVector, vector); - } - - private RAbstractVector createDoubleVectorBasedOnOrigin(double[] values, RAbstractVector originVector) { - RDoubleVector result = RDataFactory.createDoubleVector(values, originVector.isComplete()); - return copyAttributes.execute(result, originVector); - } - } - @RBuiltin(name = "exp", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) public abstract static class Exp extends UnaryArithmeticBuiltinNode { @@ -614,7 +496,8 @@ public class TrigExpFunctions { @Override protected void createCasts(CastBuilder casts) { - casts.toDouble(0).toDouble(1); + casts.arg(0).asDoubleVector(); + casts.arg(1).asDoubleVector(); } private double doFunDouble(double y, double x) { 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 fd3f5c4be7fc1e5796af7c05099009b31363aa49..1309e5de475eba4e880f97c5ed1757a62d7fa863 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 @@ -17,62 +17,72 @@ 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.profiles.BranchProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.RAttributable; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RS4Object; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RShareable; 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 { private final BranchProfile objectProfile = BranchProfile.create(); + private final BranchProfile shareableProfile = BranchProfile.create(); private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").allowNull().asAttributable(true, true, true); + } + @Specialization + protected RNull unClass(RNull rnull) { + return rnull; + } + @TruffleBoundary - protected Object unClass(RAbstractVector arg) { - if (arg.isObject(attrProfiles)) { - objectProfile.enter(); - RVector resultVector = arg.materialize(); - if (!resultVector.isTemporary()) { - resultVector = resultVector.copy(); - resultVector.incRefCount(); - } - return RVector.setVectorClassAttr(resultVector, null); + private static Object unClassVector(RAbstractVector arg) { + RVector<?> resultVector = arg.materialize(); + if (!resultVector.isTemporary()) { + resultVector = resultVector.copy(); + resultVector.incRefCount(); } - return arg; + return RVector.setVectorClassAttr(resultVector, null); } + // TODO: this specialization could go away if connections were simple vectors (we wouldn't need + // special method for setting class attributes then) @Specialization - protected Object unClass(RLanguage arg) { - if (arg.getClassAttr(attrProfiles) != null) { + protected Object unClass(RAbstractVector arg) { + if (arg.isObject(attrProfiles)) { objectProfile.enter(); - RLanguage resultLang = arg; - if (!resultLang.isTemporary()) { - resultLang = resultLang.copy(); - resultLang.incRefCount(); - } - resultLang.removeAttr(attrProfiles, RRuntime.CLASS_ATTR_KEY); - return resultLang; + return unClassVector(arg); } return arg; } - @Specialization - protected Object unClass(RS4Object arg) { + @Specialization(guards = "notAbstractVector(arg)") + protected Object unClass(RAttributable arg) { if (arg.getClassAttr(attrProfiles) != null) { objectProfile.enter(); - RS4Object resultS4 = arg; - if (!resultS4.isTemporary()) { - resultS4 = resultS4.copy(); - resultS4.incRefCount(); + if (arg instanceof RShareable) { + shareableProfile.enter(); + RShareable shareable = (RShareable) arg; + if (!shareable.isTemporary()) { + shareable = shareable.copy(); + shareable.incRefCount(); + } } - resultS4.removeAttr(attrProfiles, RRuntime.CLASS_ATTR_KEY); - return resultS4; + arg.removeAttr(attrProfiles, RRuntime.CLASS_ATTR_KEY); } return arg; } + + protected boolean notAbstractVector(Object arg) { + return !(arg instanceof RAbstractVector); + } } 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 0e93117dc795bbe0db17269947ff4cc17bae69ce..4fdb50c52dff15e3a70fdb7bba2f5491d3d4ba30 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -29,13 +30,15 @@ import java.util.ArrayList; import java.util.Arrays; 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.ConditionProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.Utils; 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.RComplexVector; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -53,9 +56,9 @@ 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; -// Implements default S3 method -@RBuiltin(name = "unique", kind = INTERNAL, parameterNames = {"x", "incomparables", "fromLast", "nmax", "..."}, behavior = PURE) +@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 @@ -65,15 +68,30 @@ public abstract class Unique extends RBuiltinNode { private final ConditionProfile bigProfile = ConditionProfile.createBinaryProfile(); + @Override + protected void createCasts(CastBuilder casts) { + // 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(); + // 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("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) + casts.arg("nmax").asIntegerVector().findFirst(RRuntime.INT_NA); + } + @SuppressWarnings("unused") @Specialization - protected RNull doUnique(RNull vec, byte incomparables, byte fromLast, Object nmax, RArgsValuesAndNames vararg) { + protected RNull doUnique(RNull vec, RAbstractVector incomparables, byte fromLast, int nmax) { return vec; } @SuppressWarnings("unused") @Specialization - protected RStringVector doUnique(RAbstractStringVector vec, byte incomparables, byte fromLast, Object nmax, RArgsValuesAndNames vararg) { + protected RStringVector doUnique(RAbstractStringVector vec, RAbstractVector incomparables, byte fromLast, int nmax) { if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) { Utils.NonRecursiveHashSet<String> set = new Utils.NonRecursiveHashSet<>(vec.getLength()); String[] data = new String[vec.getLength()]; @@ -175,7 +193,7 @@ public abstract class Unique extends RBuiltinNode { public boolean contains(RComplex val) { for (int i = 0; i < index; i++) { - if (backingArray[i << 1] == val.getRealPart() && backingArray[i << 1 + 1] == val.getImaginaryPart()) { + if (backingArray[i << 1] == val.getRealPart() && backingArray[(i << 1) + 1] == val.getImaginaryPart()) { return true; } } @@ -229,7 +247,7 @@ public abstract class Unique extends RBuiltinNode { @SuppressWarnings("unused") @Specialization - protected RIntVector doUnique(RAbstractIntVector vec, byte incomparables, byte fromLast, Object nmax, RArgsValuesAndNames vararg) { + protected RIntVector doUnique(RAbstractIntVector vec, RAbstractVector incomparables, byte fromLast, int nmax) { if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) { NonRecursiveHashSetInt set = new NonRecursiveHashSetInt(); int[] data = new int[16]; @@ -258,7 +276,7 @@ public abstract class Unique extends RBuiltinNode { @SuppressWarnings("unused") @Specialization(guards = "lengthOne(list)") - protected RList doUniqueL1(RList list, byte incomparables, byte fromLast, Object nmax, RArgsValuesAndNames vararg) { + protected RList doUniqueL1(RList list, RAbstractVector incomparables, byte fromLast, int nmax) { return (RList) list.copyDropAttributes(); } @@ -274,7 +292,8 @@ public abstract class Unique extends RBuiltinNode { @SuppressWarnings("unused") @Specialization(guards = "!lengthOne(list)") - protected RList doUnique(RList list, byte incomparables, byte fromLast, Object nmax, RArgsValuesAndNames vararg) { + @TruffleBoundary + protected RList doUnique(RList list, RAbstractVector incomparables, byte fromLast, int nmax) { /* * 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 @@ -353,7 +372,7 @@ public abstract class Unique extends RBuiltinNode { @SuppressWarnings("unused") @Specialization - protected RDoubleVector doUnique(RAbstractDoubleVector vec, byte incomparables, byte fromLast, Object nmax, RArgsValuesAndNames vararg) { + protected RDoubleVector doUnique(RAbstractDoubleVector vec, RAbstractVector incomparables, byte fromLast, int nmax) { if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) { Utils.NonRecursiveHashSetDouble set = new Utils.NonRecursiveHashSetDouble(vec.getLength()); double[] data = new double[vec.getLength()]; @@ -379,7 +398,7 @@ public abstract class Unique extends RBuiltinNode { @SuppressWarnings("unused") @Specialization - protected RLogicalVector doUnique(RAbstractLogicalVector vec, byte incomparables, byte fromLast, Object nmax, RArgsValuesAndNames vararg) { + protected RLogicalVector doUnique(RAbstractLogicalVector vec, RAbstractVector incomparables, byte fromLast, int nmax) { ByteArray dataList = new ByteArray(vec.getLength()); for (int i = 0; i < vec.getLength(); i++) { byte val = vec.getDataAt(i); @@ -392,7 +411,7 @@ public abstract class Unique extends RBuiltinNode { @SuppressWarnings("unused") @Specialization - protected RComplexVector doUnique(RAbstractComplexVector vec, byte incomparables, byte fromLast, Object nmax, RArgsValuesAndNames vararg) { + protected RComplexVector doUnique(RAbstractComplexVector vec, RAbstractVector incomparables, byte fromLast, int nmax) { if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) { Utils.NonRecursiveHashSet<RComplex> set = new Utils.NonRecursiveHashSet<>(vec.getLength()); double[] data = new double[vec.getLength() * 2]; @@ -419,7 +438,7 @@ public abstract class Unique extends RBuiltinNode { @SuppressWarnings("unused") @Specialization - protected RRawVector doUnique(RAbstractRawVector vec, byte incomparables, byte fromLast, Object nmax, RArgsValuesAndNames vararg) { + protected RRawVector doUnique(RAbstractRawVector vec, RAbstractVector incomparables, byte fromLast, int nmax) { if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) { Utils.NonRecursiveHashSet<RRaw> set = new Utils.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 d440e5ec6417d32322adaff051b0f0dbaff3bbdb..24a85cc03ca859cd643b520a2a2cbf5e50d267bb 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 @@ -11,11 +11,13 @@ */ 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.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.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; @@ -28,6 +30,7 @@ import com.oracle.truffle.r.nodes.unary.PrecedenceNodeGen; 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.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -47,8 +50,8 @@ public abstract class Unlist extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.firstBoolean(1); - casts.firstBoolean(2); + casts.arg("recursive").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).map(toBoolean()); + casts.arg("use.names").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).map(toBoolean()); } @Child private PrecedenceNode precedenceNode = PrecedenceNodeGen.create(); @@ -143,21 +146,9 @@ public abstract class Unlist extends RBuiltinNode { return RNull.instance; } - @SuppressWarnings("unused") - @Specialization(guards = "!isVectorList(vector)") - protected RAbstractVector unlistVector(RAbstractVector vector, boolean recursive, boolean useNames) { - return vector; - } - @SuppressWarnings("unused") @Specialization(guards = "isEmpty(list)") - protected RNull unlistEmptyList(VirtualFrame frame, RList list, boolean recursive, boolean useNames) { - return RNull.instance; - } - - @SuppressWarnings("unused") - @Specialization(guards = "isOneNull(list)") - protected RNull unlistOneNullList(VirtualFrame frame, RList list, boolean recursive, boolean useNames) { + protected RNull unlistEmptyList(RList list, boolean recursive, boolean useNames) { return RNull.instance; } @@ -184,6 +175,12 @@ public abstract class Unlist extends RBuiltinNode { } } + @SuppressWarnings("unused") + @Fallback + protected Object unlist(Object o, Object recursive, Object useNames) { + return o; + } + @TruffleBoundary private RAbstractVector unlistHelper(RList list, boolean recursive, boolean useNames, int precedence, int totalSize) { String[] namesData = useNames ? new String[totalSize] : null; @@ -650,7 +647,15 @@ public abstract class Unlist extends RBuiltinNode { } private static String unlistValueString(Object cur) { - return RRuntime.toString(cur); + if (cur instanceof Double) { + Double d = (Double) cur; + return RRuntime.isNAorNaN(d) ? RRuntime.STRING_NA : RContext.getRRuntimeASTAccess().encodeDouble(d); + } else if (cur instanceof RComplex) { + RComplex c = (RComplex) cur; + return c.isNA() ? RRuntime.STRING_NA : RContext.getRRuntimeASTAccess().encodeComplex(c); + } else { + return RRuntime.toString(cur); + } } private static RComplex unlistValueComplex(Object dataAtAsObject) { 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 8741f2c60c92f5df943fd3cec2bd421d6c2a34ea..add4672b6bf682fd1cac1d3a2f4d29c5540d2452 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 @@ -22,6 +22,9 @@ */ 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; @@ -31,6 +34,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.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.unary.CastIntegerNode; import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; @@ -38,9 +42,9 @@ 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.runtime.RError; -import com.oracle.truffle.r.runtime.RError.Message; -import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -66,6 +70,14 @@ public abstract class UpdateAttr extends RBuiltinNode { @CompilationFinal private String cachedName = ""; @CompilationFinal private String cachedInternedName = ""; + @Override + protected void createCasts(CastBuilder casts) { + // 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(); + } + private RAbstractContainer updateNames(RAbstractContainer container, Object o) { if (updateNames == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -101,7 +113,7 @@ public abstract class UpdateAttr extends RBuiltinNode { private String intern(String name) { if (cachedName == null) { // unoptimized case - return name.intern(); + return Utils.intern(name); } if (cachedName == name) { // cached case @@ -112,12 +124,12 @@ public abstract class UpdateAttr extends RBuiltinNode { if (cachedName == "") { // Checkstyle: resume StringLiteralEquality cachedName = name; - cachedInternedName = name.intern(); + cachedInternedName = Utils.intern(name); } else { cachedName = null; cachedInternedName = null; } - return name.intern(); + return Utils.intern(name); } @Specialization @@ -180,11 +192,6 @@ public abstract class UpdateAttr extends RBuiltinNode { return result; } - @Specialization(guards = "!nullValue(value)") - protected RAbstractContainer updateAttr(RAbstractVector vector, RStringVector name, Object value) { - return updateAttr(vector, name.getDataAt(0), value); - } - // 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) { @@ -196,16 +203,12 @@ public abstract class UpdateAttr extends RBuiltinNode { */ @Fallback protected Object updateAttr(Object obj, Object name, Object value) { + assert name instanceof String : "casts should not pass anything but String"; Object object = obj; - String sname = RRuntime.asString(name); - if (sname == null) { - errorProfile.enter(); - throw RError.error(this, RError.Message.MUST_BE_NONNULL_STRING, "name"); - } if (object instanceof RShareable) { object = ((RShareable) object).getNonShared(); } - String internedName = intern(sname); + String internedName = intern((String) name); if (object instanceof RAttributable) { RAttributable attributable = (RAttributable) object; if (value == RNull.instance) { @@ -215,12 +218,7 @@ public abstract class UpdateAttr extends RBuiltinNode { } return object; } else { - errorProfile.enter(); - if (object instanceof RNull) { - throw RError.error(this, Message.GENERIC, "attempt to set an attribute on NULL"); - } else { - throw RError.nyi(this, "object cannot be attributed"); - } + throw RError.nyi(this, "object cannot be attributed"); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java index 49b6186f09b7f8ab61fbc1868916c3f2d2efe425..8620bf9d008dbff0a75e938e0f8ad29f8a240dbd 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 @@ -22,18 +22,19 @@ */ 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.runtime.RError.Message.ATTRIBUTES_LIST_OR_NULL; 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.CompilerDirectives.TruffleBoundary; -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.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastIntegerNode; 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.runtime.RError; @@ -45,6 +46,7 @@ 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; @@ -58,25 +60,32 @@ public abstract class UpdateAttributes extends RBuiltinNode { @Child private UpdateDimNames updateDimNames; @Child private CastIntegerNode castInteger; @Child private CastToVectorNode castVector; - @Child private CastListNode castList; + + @Override + protected void createCasts(CastBuilder casts) { + // Note: cannot check 'attributability' easily because atomic values, e.g int, are not + // RAttributable. + casts.arg("obj"); // by default disallows RNull + casts.arg("value").conf(c -> c.allowNull()).mustBe(instanceOf(RList.class), this, ATTRIBUTES_LIST_OR_NULL); + } // it's OK for the following two methods to update attributes in-place as the container has been // already materialized to non-shared - private void updateNames(RAbstractContainer container, Object o) { + private RAbstractContainer updateNames(RAbstractContainer container, Object o) { if (updateNames == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); updateNames = insert(UpdateNamesNodeGen.create(null)); } - updateNames.executeStringVector(container, o); + return (RAbstractContainer) updateNames.executeStringVector(container, o); } - private void updateDimNames(RAbstractContainer container, Object o) { + private RAbstractContainer updateDimNames(RAbstractContainer container, Object o) { if (updateDimNames == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); updateDimNames = insert(UpdateDimNamesNodeGen.create(null)); } - updateDimNames.executeRAbstractContainer(container, o); + return updateDimNames.executeRAbstractContainer(container, o); } private RAbstractIntVector castInteger(RAbstractVector vector) { @@ -96,8 +105,8 @@ public abstract class UpdateAttributes extends RBuiltinNode { } @Specialization - protected RAbstractVector updateAttributes(RAbstractVector abstractVector, @SuppressWarnings("unused") RNull list) { - RAbstractVector resultVector = (RAbstractVector) abstractVector.getNonShared(); + protected RAbstractContainer updateAttributes(RAbstractContainer abstractContainer, @SuppressWarnings("unused") RNull list) { + RAbstractContainer resultVector = (RAbstractContainer) abstractContainer.getNonShared(); resultVector.resetAllAttributes(true); return resultVector; } @@ -176,9 +185,9 @@ public abstract class UpdateAttributes extends RBuiltinNode { if (attrName.equals(RRuntime.DIM_ATTR_KEY)) { continue; } else if (attrName.equals(RRuntime.NAMES_ATTR_KEY)) { - updateNames(res, value); + res = updateNames(res, value); } else if (attrName.equals(RRuntime.DIMNAMES_ATTR_KEY)) { - updateDimNames(res, value); + res = updateDimNames(res, value); } else if (attrName.equals(RRuntime.CLASS_ATTR_KEY)) { if (value == RNull.instance) { res = (RAbstractContainer) result.setClassAttr(null); @@ -198,48 +207,68 @@ 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. + * All other, non-performance centric, {@link RAttributable} types, or error case for RNull + * value. */ - @Fallback + @Specialization(guards = {"!isAbstractContainer(o)"}) @TruffleBoundary - protected Object doOther(Object o, Object operand) { - Object obj = o; - if (obj instanceof RShareable) { - obj = ((RShareable) obj).getNonShared(); + protected Object doOtherNull(Object o, @SuppressWarnings("unused") RNull 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(attrProfiles); + if (listNames == null) { + throw RError.error(this, RError.Message.ATTRIBUTES_NAMED); } - if (obj instanceof RAttributable) { - RAttributable attrObj = (RAttributable) obj; - attrObj.removeAllAttributes(); - if (operand == RNull.instance) { - attrObj.setClassAttr(null); - } else if (operand instanceof RList) { - RList list = (RList) operand; - RStringVector listNames = list.getNames(attrProfiles); - if (listNames == null) { - throw RError.error(this, RError.Message.ATTRIBUTES_NAMED); - } - for (int i = 0; i < list.getLength(); i++) { - String attrName = listNames.getDataAt(i); - if (attrName == null) { - throw RError.error(this, RError.Message.ATTRIBUTES_NAMED); - } - if (attrName.equals(RRuntime.CLASS_ATTR_KEY)) { - Object attrValue = list.getDataAt(i); - if (attrValue == null) { - throw RError.error(this, RError.Message.SET_INVALID_CLASS_ATTR); - } - attrObj.setClassAttr(UpdateAttr.convertClassAttrFromObject(attrValue)); - } else { - attrObj.setAttr(attrName, list.getDataAt(i)); - } + 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 (attrName.equals(RRuntime.CLASS_ATTR_KEY)) { + Object attrValue = operand.getDataAt(i); + if (attrValue == null) { + throw RError.error(this, RError.Message.SET_INVALID_CLASS_ATTR); } + attrObj.setClassAttr(UpdateAttr.convertClassAttrFromObject(attrValue)); } else { - throw RError.error(this, RError.Message.ATTRIBUTES_LIST_OR_NULL); + attrObj.setAttr(attrName, operand.getDataAt(i)); } - } else { + } + return obj; + } + + private void checkAttributable(Object obj) { + if (!(obj instanceof RAttributable)) { throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); } + } + + private static Object getNonShared(Object obj) { + if (obj instanceof RShareable) { + return ((RShareable) obj).getNonShared(); + } return obj; } } 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 25207ed80eabb2649f34aff15ec6b84215f3dc85..62799507ade961086ec2c43d64c72aa344899b69 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 @@ -21,9 +21,8 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.attributes.TypeFromModeNode; import com.oracle.truffle.r.nodes.binary.CastTypeNode; import com.oracle.truffle.r.nodes.binary.CastTypeNodeGen; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.unary.TypeofNode; import com.oracle.truffle.r.nodes.unary.TypeofNodeGen; import com.oracle.truffle.r.runtime.RError; @@ -35,7 +34,6 @@ import com.oracle.truffle.r.runtime.data.RExternalPtr; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RS4Object; -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.model.RAbstractContainer; @@ -49,33 +47,20 @@ public abstract class UpdateClass extends RBuiltinNode { protected static final int CACHE_LIMIT = 2; @Child private CastTypeNode castTypeNode; - @Child private CastStringNode castStringNode; @Child private TypeofNode typeof; private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); - @Specialization(guards = "!isStringVector(className)") - protected Object setClass(RAbstractContainer arg, RAbstractVector className) { - if (className.getLength() == 0) { - return setClass(arg, RNull.instance); - } - initCastStringNode(); - Object result = castStringNode.execute(className); - return setClass(arg, (RStringVector) result); - } - - private void initCastStringNode() { - if (castStringNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castStringNode = insert(CastStringNodeGen.create(false, false, false, false)); - } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x"); // disallows null + casts.arg("value").allowNull().asStringVector(); } @Specialization @TruffleBoundary protected Object setClass(RAbstractContainer arg, @SuppressWarnings("unused") RNull className) { - - RAbstractContainer result = (RAbstractContainer) arg.getNonShared(); + RAbstractContainer result = reuseNonShared(arg); return result.setClassAttr(null); } @@ -109,7 +94,7 @@ public abstract class UpdateClass extends RBuiltinNode { return setClass((RAbstractVector) result, RNull.instance); } } - RAbstractContainer result = (RAbstractContainer) arg.getNonShared(); + RAbstractContainer result = reuseNonShared(arg); if (result instanceof RAbstractVector) { RAbstractVector resultVector = (RAbstractVector) result; if (RType.Matrix.getName().equals(className)) { @@ -135,7 +120,7 @@ public abstract class UpdateClass extends RBuiltinNode { @Specialization @TruffleBoundary protected Object setClass(RAbstractContainer arg, RStringVector className) { - RAbstractContainer result = (RAbstractContainer) arg.getNonShared(); + RAbstractContainer result = reuseNonShared(arg); return result.setClassAttr(className); } @@ -199,6 +184,11 @@ public abstract class UpdateClass extends RBuiltinNode { return arg; } + @SuppressWarnings("unchecked") + private static <T extends RAbstractContainer> T reuseNonShared(T obj) { + return (T) obj.getNonShared(); + } + private void initCastTypeNode() { if (castTypeNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -212,8 +202,4 @@ public abstract class UpdateClass extends RBuiltinNode { typeof = insert(TypeofNodeGen.create()); } } - - 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/UpdateDim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java index 9d255dec5bf0fe26971533f3867a15a6f6f27547..38c7b1c09aca3d8ce2fbcf622a2469ceeaf83d86 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 @@ -22,17 +22,20 @@ */ 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.runtime.RError.Message.LENGTH_ZERO_DIM_INVALID; 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.Cached; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.attributes.InitAttributesNode; +import com.oracle.truffle.r.nodes.attributes.PutAttributeNode; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.opt.ReuseNonSharedNode; -import com.oracle.truffle.r.nodes.unary.CastIntegerNode; -import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -43,24 +46,31 @@ public abstract class UpdateDim extends RBuiltinNode { @Child private ReuseNonSharedNode reuse = ReuseNonSharedNode.create(); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x"); // disallows null + casts.arg("value").allowNull().asIntegerVector().mustBe(notEmpty(), this, LENGTH_ZERO_DIM_INVALID); + } + @Specialization protected RAbstractVector updateDim(RAbstractVector vector, @SuppressWarnings("unused") RNull dimensions) { - RVector result = ((RAbstractVector) reuse.execute(vector)).materialize(); + RVector<?> result = ((RAbstractVector) reuse.execute(vector)).materialize(); result.resetDimensions(null); return result; } @Specialization - protected RAbstractVector updateDim(RAbstractVector vector, RAbstractVector dimensions, // - @Cached("createPreserveNames()") CastIntegerNode castInteger) { - if (dimensions.getLength() == 0) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.LENGTH_ZERO_DIM_INVALID); - } - int[] dimsData = ((RAbstractIntVector) castInteger.execute(dimensions)).materialize().getDataCopy(); + protected RAbstractVector updateDim(RAbstractVector vector, RAbstractIntVector dimensions, + @Cached("createDim()") PutAttributeNode putDimensions, + @Cached("create()") InitAttributesNode initAttributes) { + RIntVector dimensionsMaterialized = dimensions.materialize(); + int[] dimsData = dimensionsMaterialized.getDataCopy(); RVector.verifyDimensions(vector.getLength(), dimsData, this); - RVector result = ((RAbstractVector) reuse.execute(vector)).materialize(); - result.resetDimensions(dimsData); + RVector<?> result = ((RAbstractVector) reuse.execute(vector)).materialize(); + result.setInternalDimensions(dimsData); + result.setInternalNames(null); + result.setInternalDimNames(null); + putDimensions.execute(initAttributes.execute(result), dimensionsMaterialized); return result; } } 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 8bcaa7f8a2d2eef9878df405320ca0610db4bf39..d77eb154b652b762b180dd82927db291d3658158 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 @@ -24,6 +24,7 @@ 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 static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; @@ -47,7 +48,7 @@ import com.oracle.truffle.r.runtime.data.RVector; 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"}, behavior = PURE) +@RBuiltin(name = "dimnames<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE) public abstract class UpdateDimNames extends RBuiltinNode { protected static final String DIMNAMES_ATTR_KEY = RRuntime.DIMNAMES_ATTR_KEY; @@ -61,7 +62,7 @@ public abstract class UpdateDimNames extends RBuiltinNode { private Object castString(Object o) { if (castStringNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - castStringNode = insert(CastStringNodeGen.create(true, true, false, false)); + castStringNode = insert(CastStringNodeGen.create(true, true, true)); } return castStringNode.execute(o); } @@ -96,13 +97,13 @@ public abstract class UpdateDimNames extends RBuiltinNode { @Cached("create(DIMNAMES_ATTR_KEY)") RemoveAttributeNode remove) { RAbstractContainer result = (RAbstractContainer) container.getNonShared(); if (isRVectorProfile.profile(container instanceof RVector)) { - RVector vector = (RVector) container; + RVector<?> vector = (RVector<?>) result; if (vector.getInternalDimNames() != null) { vector.setInternalDimNames(null); remove.execute(vector.getAttributes()); } } else { - container.setDimNames(null); + result.setDimNames(null); } return result; } @@ -130,7 +131,7 @@ public abstract class UpdateDimNames extends RBuiltinNode { private void setDimNames(RAbstractContainer container, RList newDimNames, PutAttributeNode put) { assert newDimNames != null; if (isRVectorProfile.profile(container instanceof RVector)) { - RVector vector = (RVector) container; + RVector<?> vector = (RVector<?>) container; int[] dimensions = vector.getDimensions(); if (dimensions == null) { CompilerDirectives.transferToInterpreter(); 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 5d5f36d2a5b57d57d5583cb93ddca5b7cb2bcfc7..67a5eae4cbc6df624c278543a6198e9318c3cd31 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 @@ -22,47 +22,46 @@ */ 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.doubleValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; +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.RDispatch.INTERNAL_GENERIC; +import static com.oracle.truffle.r.runtime.RError.Message.INVALID_UNNAMED_ARGUMENT; +import static com.oracle.truffle.r.runtime.RError.Message.INVALID_UNNAMED_VALUE; 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.Specialization; import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @RBuiltin(name = "length<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE) public abstract class UpdateLength extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.toInteger(1, true, false, false); + // Note: `length<-`(NULL, newLen) really works in GnuR unlike other update builtins + // @formatter:off + casts.arg("x").conf(c -> c.allowNull()).mustBe(abstractVectorValue(), this, INVALID_UNNAMED_ARGUMENT); + casts.arg("value").defaultError(this, INVALID_UNNAMED_VALUE). + mustBe(integerValue().or(doubleValue()).or(stringValue())). + asIntegerVector().mustBe(singleElement()).findFirst(); + // @formatter:on } @SuppressWarnings("unused") - @Specialization(guards = "isLengthOne(lengthVector)") - protected RNull updateLength(RNull value, RAbstractIntVector lengthVector) { + @Specialization + protected RNull updateLength(RNull value, int length) { return RNull.instance; } - @Specialization(guards = "isLengthOne(lengthVector)") - protected RAbstractContainer updateLength(RAbstractContainer container, RAbstractIntVector lengthVector) { - return container.resize(lengthVector.getDataAt(0)); - } - - @SuppressWarnings("unused") @Specialization - protected Object updateLengthError(Object vector, Object lengthVector) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_UNNAMED_VALUE); - } - - protected static boolean isLengthOne(RAbstractIntVector length) { - return length.getLength() == 1; + protected RAbstractContainer updateLength(RAbstractContainer container, int length) { + return container.resize(length); } } 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 5ffaf8da7fb1c5c4457f4a87c73b2971c52c6241..003fb96b284730de7da4a616d917c24c3f2d541e 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 @@ -44,14 +44,14 @@ public abstract class UpdateLevels extends RBuiltinNode { @Specialization protected RAbstractVector updateLevels(RAbstractVector vector, @SuppressWarnings("unused") RNull levels) { - RVector v = (RVector) vector.getNonShared(); + RVector<?> v = (RVector<?>) vector.getNonShared(); v.removeAttr(attrProfiles, RRuntime.LEVELS_ATTR_KEY); return v; } @Specialization(guards = "levelsNotNull(levels)") protected RAbstractVector updateLevels(RAbstractVector vector, Object levels) { - RVector v = (RVector) vector.getNonShared(); + RVector<?> v = (RVector<?>) vector.getNonShared(); v.setAttr(RRuntime.LEVELS_ATTR_KEY, castVector(levels)); return v; } 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 f19d251da239e99870eb9e1bef37b34bbfc0a428..660ac299a279bb3b6782f368481d544f65c7f3c1 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 @@ -24,6 +24,7 @@ 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 static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -40,7 +41,7 @@ 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; -@RBuiltin(name = "names<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, behavior = PURE) +@RBuiltin(name = "names<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE) public abstract class UpdateNames extends RBuiltinNode { @Child private CastStringNode castStringNode; @@ -48,7 +49,7 @@ public abstract class UpdateNames extends RBuiltinNode { private Object castString(Object o) { if (castStringNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - castStringNode = insert(CastStringNodeGen.create(false, true, false, false)); + castStringNode = insert(CastStringNodeGen.create(false, false, false)); } return castStringNode.executeString(o); } @@ -69,16 +70,20 @@ public abstract class UpdateNames extends RBuiltinNode { if (newNames instanceof String) { stringVector = RDataFactory.createStringVector((String) newNames); } else { - stringVector = (RStringVector) ((RAbstractVector) newNames).materialize(); + 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()); - } else if (stringVector == container) { + } 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 963fb48e49d9bc006ffb8007ca700d4a03560932..f05261a585f42113af69f41576f5a2897eddc6df 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 @@ -59,7 +59,7 @@ public abstract class UpdateOldClass extends RBuiltinNode { private void initCastStringNode() { if (castStringNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - castStringNode = insert(CastStringNodeGen.create(false, false, false, false)); + castStringNode = insert(CastStringNodeGen.create(false, false, false)); } } 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 b549fede5a4879ec25b1cc2f1f3c9e40dea1a39e..a78fde5483d585c723197e1b9fdd90967a7b9f0a 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 @@ -18,11 +18,9 @@ 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.Truffle; 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.DirectCallNode; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.UpdateSlotNode; @@ -33,7 +31,7 @@ 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.signature.RArgumentsNode; +import com.oracle.truffle.r.nodes.function.call.CallRFunctionNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RError; @@ -55,13 +53,12 @@ public abstract class UpdateSlot extends RBuiltinNode { @Child private ClassHierarchyNode valClassHierarchy; @Child private UpdateSlotNode updateSlotNode = com.oracle.truffle.r.nodes.access.UpdateSlotNodeGen.create(null, null, null); @Child private ReadVariableNode checkAtAssignmentFind = ReadVariableNode.createFunctionLookup(RSyntaxNode.INTERNAL, "checkAtAssignment"); - @Child private DirectCallNode checkAtAssignmentCall; - @Child private RArgumentsNode argsNode = RArgumentsNode.create(); + @Child private CallRFunctionNode checkAtAssignmentCall; private final ConditionProfile cached = ConditionProfile.createBinaryProfile(); @Override protected void createCasts(CastBuilder casts) { - casts.toAttributable(0, true, true, true); + casts.arg(0).allowNull().asAttributable(true, true, true); } protected String getName(Object nameObj) { @@ -93,7 +90,7 @@ public abstract class UpdateSlot extends RBuiltinNode { if (checkSlotAssignFunction == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); checkSlotAssignFunction = (RFunction) checkAtAssignmentFind.execute(frame); - checkAtAssignmentCall = insert(Truffle.getRuntime().createDirectCallNode(checkSlotAssignFunction.getTarget())); + checkAtAssignmentCall = insert(CallRFunctionNode.create(checkSlotAssignFunction.getTarget())); assert objClassHierarchy == null && valClassHierarchy == null; objClassHierarchy = insert(ClassHierarchyNodeGen.create(true, false)); valClassHierarchy = insert(ClassHierarchyNodeGen.create(true, false)); @@ -105,8 +102,8 @@ public abstract class UpdateSlot extends RBuiltinNode { if (cached.profile(currentFunction == checkSlotAssignFunction)) { // TODO: technically, someone could override checkAtAssignment function and access the // caller, but it's rather unlikely - Object[] args = argsNode.execute(checkSlotAssignFunction, RCaller.create(frame, getOriginalCall()), null, new Object[]{objClass, name, valClass}, SIGNATURE, null); - checkAtAssignmentCall.call(frame, args); + 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); 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 23a86b5adf58dbb178712156bdcd4a0954898ad6..b02742a85df21f1fb7491384b55e60a63e6c338a 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 @@ -28,6 +28,7 @@ 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.RType; +import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RAttributes; @@ -82,7 +83,7 @@ public abstract class UpdateStorageMode extends RBuiltinNode { rresult = (RAbstractContainer) rresult.setClassAttr((RStringVector) v); } } else { - rresult.setAttr(attrName.intern(), v); + rresult.setAttr(Utils.intern(attrName), v); } } return rresult; @@ -120,6 +121,6 @@ public abstract class UpdateStorageMode extends RBuiltinNode { @Specialization protected Object update(Object x, Object value) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.NULL_VALUE); + throw RError.error(this, RError.Message.MUST_BE_NONNULL_STRING, "value"); } } 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 2ca786f9606fe2ece085ae40a0f5552564e46999..2fdba2452bbd296c15841f87e7aead60fb576a88 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 @@ -22,15 +22,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.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; 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.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.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.Lapply.LapplyInternalNode; import com.oracle.truffle.r.nodes.builtin.base.LapplyNodeGen.LapplyInternalNodeGen; @@ -76,10 +78,8 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "vapply", kind = INTERNAL, parameterNames = {"X", "FUN", "FUN.VALUE", "USE.NAMES"}, splitCaller = true, behavior = COMPLEX) public abstract class VApply extends RBuiltinNode { - private final ValueProfile funValueProfile = ValueProfile.createClassProfile(); private final ConditionProfile useNamesProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile dimsProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile errorProfile = BranchProfile.create(); private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); private final NACheck naCheck = NACheck.create(); @@ -91,6 +91,17 @@ public abstract class VApply extends RBuiltinNode { @Child private CastLogicalNode castLogical; @Child private CastStringNode castString; + @Override + protected void createCasts(CastBuilder casts) { + 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(); + } + private Object castComplex(Object operand, boolean preserveAllAttr) { if (castComplex == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -126,37 +137,31 @@ public abstract class VApply extends RBuiltinNode { private Object castString(Object operand, boolean preserveAllAttr) { if (castString == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - castString = insert(CastStringNodeGen.create(false, true, preserveAllAttr, preserveAllAttr)); + castString = insert(CastStringNodeGen.create(true, preserveAllAttr, preserveAllAttr)); } return castString.execute(operand); } @Specialization - protected Object vapply(VirtualFrame frame, RAbstractVector vec, RFunction fun, Object funValue, byte useNames) { - RVector result = delegateToLapply(frame, vec, fun, funValue, useNames); + 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; } - private RVector delegateToLapply(VirtualFrame frame, RAbstractVector vec, RFunction fun, Object funValueArg, byte useNames) { + private RVector<?> delegateToLapply(VirtualFrame frame, RAbstractVector vec, RFunction fun, RAbstractVector funValueVec, byte 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 * both funValueArg and the result of the doApply. At a slight performance cost this code * works exclusively in terms of concrete vectors. */ - Object funValueObj = RRuntime.asAbstractVector(funValueArg); - if (!(funValueObj instanceof RAbstractVector)) { - errorProfile.enter(); - throw RError.error(this, RError.Message.MUST_BE_VECTOR, "FUN.VALUE"); - } - RAbstractVector funValueVec = funValueProfile.profile((RAbstractVector) funValueObj); int funValueVecLen = funValueVec.getLength(); - RVector vecMat = vec.materialize(); + RVector<?> vecMat = vec.materialize(); Object[] applyResult = doApply.execute(frame, vecMat, fun); - RVector result = null; + RVector<?> result = null; boolean applyResultZeroLength = applyResult.length == 0; naCheck.enable(true); 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 5736f617e756325463f3b84daf925551432de5d6..c942eacc8a4a562af2a4749cd517b0b1cdb63e8f 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 @@ -47,7 +47,8 @@ public abstract class Vector extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.arg("length").asIntegerVector().mustBe(singleElement()).findFirst(); + 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(); } protected RType modeToType(String mode) { 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 c507722d2142f8f4c7f7af14015a6fff56d4c620..64b2b539db2bc7035e609b4a8ef40b3d31008094 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 @@ -22,58 +22,38 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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.INTERNAL; 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.builtin.CastBuilder; 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.runtime.RErrorHandling; -import com.oracle.truffle.r.runtime.RRuntime; 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 { - @Child private CastStringNode castString; - - private Object castString(Object operand) { - if (castString == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castString = insert(CastStringNodeGen.create(false, true, false, false)); - } - return castString.execute(operand); - } - @Override protected void createCasts(CastBuilder casts) { - casts.toLogical(0); - casts.toLogical(1); - casts.toLogical(2); + casts.arg("call").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("immediate").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("nobreaks").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("message").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.INVALID_STRING_IN_WARNING).findFirst(); + } @Specialization @TruffleBoundary - protected String warning(byte callL, byte immediateL, byte noBreakWarningL, Object messageObj) { - String message = RRuntime.asString(castString(messageObj)); - boolean call = RRuntime.fromLogical(callL); - boolean immediate = RRuntime.fromLogical(immediateL); - boolean noBreakWarning = RRuntime.fromLogical(noBreakWarningL); + protected String warning(boolean call, boolean immediate, boolean noBreakWarning, String message) { + CompilerDirectives.transferToInterpreter(); RErrorHandling.warningcallInternal(call, message, immediate, noBreakWarning); return message; } - @SuppressWarnings("unused") - @Fallback - @TruffleBoundary - protected String warning(Object callL, Object immediateL, Object noBreakWarningL, Object message) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); - } } 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 ffa0cc5c29b71e409b06dadc9080542cfd02c7cb..5377d697ab2fc5f68b2fcb7ee8b4566403db99c1 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 @@ -22,23 +22,29 @@ */ 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.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; -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.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.LoopConditionProfile; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.base.WhichFunctionsFactory.WhichMaxNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.WhichFunctionsFactory.WhichMinNodeGen; +import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; 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.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; +import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.ops.na.NACheck; /** @@ -49,94 +55,125 @@ public class WhichFunctions { @RBuiltin(name = "which", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) public abstract static class Which extends RBuiltinNode { - private final NACheck naCheck = NACheck.create(); - private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(logicalValue()).asLogicalVector(); + } - @Specialization(guards = "!hasNames(x)") - @TruffleBoundary - protected RIntVector which(RAbstractLogicalVector x) { - ArrayList<Integer> w = new ArrayList<>(); - for (int i = 0; i < x.getLength(); i++) { + @Specialization + protected RIntVector which(RAbstractLogicalVector x, + @Cached("create()") VectorLengthProfile lengthProfile, + @Cached("createCountingProfile()") LoopConditionProfile loopProfile, + @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile, + @Cached("create()") RAttributeProfiles attrProfiles, + @Cached("create()") NACheck naCheck) { + int length = lengthProfile.profile(x.getLength()); + loopProfile.profileCounted(length); + // determine the length of the result + int resultLength = 0; + for (int i = 0; loopProfile.inject(i < length); i++) { if (x.getDataAt(i) == RRuntime.LOGICAL_TRUE) { - w.add(i); + resultLength++; } } - int[] result = new int[w.size()]; - for (int i = 0; i < result.length; i++) { - result[i] = w.get(i) + 1; - } - return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR); - } - - @Specialization(guards = "hasNames(x)") - @TruffleBoundary - protected RIntVector whichNames(RAbstractLogicalVector x) { - ArrayList<Integer> w = new ArrayList<>(); - ArrayList<String> n = new ArrayList<>(); - RStringVector oldNames = x.getNames(attrProfiles); - naCheck.enable(oldNames); - for (int i = 0; i < x.getLength(); i++) { + // collect result indexes + int[] result = new int[resultLength]; + int pos = 0; + for (int i = 0; loopProfile.inject(i < length); i++) { if (x.getDataAt(i) == RRuntime.LOGICAL_TRUE) { - w.add(i); - String s = oldNames.getDataAt(i); - naCheck.check(s); - n.add(s); + result[pos++] = i + 1; } } - int[] result = new int[w.size()]; - for (int i = 0; i < result.length; i++) { - result[i] = w.get(i) + 1; + RStringVector names = x.getNames(attrProfiles); + if (hasNamesProfile.profile(names != null)) { + // collect result names + String[] resultNames = new String[resultLength]; + naCheck.enable(names); + pos = 0; + for (int i = 0; i < x.getLength(); i++) { + if (x.getDataAt(i) == RRuntime.LOGICAL_TRUE) { + String name = names.getDataAt(i); + naCheck.check(name); + resultNames[pos++] = name; + } + } + return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR, RDataFactory.createStringVector(resultNames, naCheck.neverSeenNA())); + } else { + return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR); } - String[] names = new String[n.size()]; - return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR, RDataFactory.createStringVector(n.toArray(names), naCheck.neverSeenNA())); - } - - protected boolean hasNames(RAbstractLogicalVector x) { - return x.getNames(attrProfiles) != null; } } - @RBuiltin(name = "which.max", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) - public abstract static class WhichMax extends RBuiltinNode { + public abstract static class WhichMinMax extends RBuiltinNode { + + private final boolean isMax; + + protected WhichMinMax(boolean isMax) { + this.isMax = isMax; + } @Override protected void createCasts(CastBuilder casts) { - casts.toDouble(0); + casts.arg(0, "x").allowNull().asDoubleVector(true, false, false); } @Specialization - protected int which(RAbstractDoubleVector x) { - double max = x.getDataAt(0); - int maxIndex = 0; - for (int i = 0; i < x.getLength(); i++) { - if (x.getDataAt(i) > max) { - max = x.getDataAt(i); - maxIndex = i; + protected RIntVector which(RAbstractDoubleVector x, + @Cached("create()") VectorLengthProfile lengthProfile, + @Cached("createCountingProfile()") LoopConditionProfile loopProfile, + @Cached("createBinaryProfile()") ConditionProfile isNaNProfile, + @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile, + @Cached("create()") RAttributeProfiles attrProfiles) { + int length = lengthProfile.profile(x.getLength()); + loopProfile.profileCounted(length); + double extreme = Double.NaN; + int extremeIndex = -1; + for (int i = 0; loopProfile.inject(i < length); i++) { + double d = x.getDataAt(i); + // inverted comparison to pass when extreme is NaN + if (!Double.isNaN(d) && (isMax ? !(d <= extreme) : !(d >= extreme))) { + extreme = x.getDataAt(i); + extremeIndex = i; } } - return maxIndex + 1; + if (isNaNProfile.profile(extremeIndex == -1)) { + return RDataFactory.createEmptyIntVector(); + } + RStringVector names = x.getNames(attrProfiles); + if (hasNamesProfile.profile(names != null)) { + // collect result names + RStringVector resultNames = RDataFactory.createStringVectorFromScalar(names.getDataAt(extremeIndex)); + return RDataFactory.createIntVector(new int[]{extremeIndex + 1}, true, resultNames); + } else { + return RDataFactory.createIntVectorFromScalar(extremeIndex + 1); + } + } + + @Specialization + protected RIntVector which(@SuppressWarnings("unused") RNull x) { + return RDataFactory.createEmptyIntVector(); } } - @RBuiltin(name = "which.min", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) - public abstract static class WhichMin extends RBuiltinNode { + @RBuiltin(name = "which.max", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) + public abstract static class WhichMax extends WhichMinMax { + protected WhichMax() { + super(true); + } - @Override - protected void createCasts(CastBuilder casts) { - casts.toDouble(0); + public static WhichMinMax create(RNode[] arguments) { + return WhichMaxNodeGen.create(arguments); } + } - @Specialization - protected int which(RAbstractDoubleVector x) { - double minimum = x.getDataAt(0); - int minIndex = 0; - for (int i = 0; i < x.getLength(); i++) { - if (x.getDataAt(i) < minimum) { - minimum = x.getDataAt(i); - minIndex = i; - } - } - return minIndex + 1; + @RBuiltin(name = "which.min", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) + public abstract static class WhichMin extends WhichMinMax { + protected WhichMin() { + super(false); + } + + public static WhichMinMax create(RNode[] arguments) { + return WhichMinNodeGen.create(arguments); } } } 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 abc807d0118d0b82c3e92ef2f59850058aebbd3a..f1bdec68e310da340ff1285a9575361b24c8c0d5 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 @@ -25,37 +25,37 @@ package com.oracle.truffle.r.nodes.builtin.base; 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.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.function.visibility.GetVisibilityNode; 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.context.RContext; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RStringVector; +// TODO The base package manual says this is a primitive but GNU R implements it as .Internal. +// That causes problems as the .Internal adds another layer of visibility setting that +// 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) public abstract class WithVisible extends RBuiltinNode { - private static final RStringVector LISTNAMES = RDataFactory.createStringVector(new String[]{"value", "visible"}, RDataFactory.COMPLETE_VECTOR); - @Specialization(guards = "!isRMissing(x)") - protected RList withVisible(Object x) { - // (LS) temporarily disabled to enable parallel benchmarks - // if (FastROptions.IgnoreVisibility.getBooleanValue()) { - // RError.warning(this, RError.Message.GENERIC, "using withVisible with IgnoreVisibility"); - // } + private static final RStringVector LISTNAMES = (RStringVector) RDataFactory.createStringVector(new String[]{"value", "visible"}, RDataFactory.COMPLETE_VECTOR).makeSharedPermanent(); - Object[] data = new Object[]{x, RRuntime.asLogical(RContext.getInstance().isVisible())}; - // Visibility is changed by the evaluation (else this code would not work), - // so we have to force it back on. - return RDataFactory.createList(data, LISTNAMES); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustNotBeMissing(RError.Message.ARGUMENT_MISSING, "x"); } @Specialization - protected RList withVisible(@SuppressWarnings("unused") RMissing x) { - throw RError.error(this, Message.ARGUMENT_MISSING, "x"); + protected RList withVisible(VirtualFrame frame, Object x, + @Cached("create()") GetVisibilityNode visibility) { + Object[] data = new Object[]{x, RRuntime.asLogical(visibility.execute(frame))}; + return RDataFactory.createList(data, LISTNAMES); } } 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 80b7588ebc14af89bc0430feece1c59ad42f3ba6..5bf2e7213d6f199894f8b941010e09345a69c826 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 @@ -24,41 +24,39 @@ package com.oracle.truffle.r.nodes.builtin.base.fastpaths; 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.base.Assign; import com.oracle.truffle.r.nodes.builtin.base.AssignNodeGen; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RFastPathNode; public abstract class AssignFastPath extends RFastPathNode { - @Child private Assign assign = AssignNodeGen.create(null); + @Child private Assign assign = AssignNodeGen.create(true, null); @Specialization @SuppressWarnings("unused") - protected Object getNonInherit(VirtualFrame frame, RAbstractStringVector x, Object value, RMissing pos, REnvironment envir, byte inherits, Object immediate) { - return assign.execute(frame, x, value, envir, inherits); + protected Object assign(String x, Object value, RMissing pos, REnvironment envir, byte inherits, Object immediate) { + return assign.execute(x, value, envir, inherits); } @Specialization @SuppressWarnings("unused") - protected Object getNonInherit(VirtualFrame frame, RAbstractStringVector x, Object value, RMissing pos, REnvironment envir, RMissing inherits, Object immediate) { - return assign.execute(frame, x, value, envir, RRuntime.LOGICAL_FALSE); + protected Object assign(String x, Object value, RMissing pos, REnvironment envir, RMissing inherits, Object immediate) { + return assign.execute(x, value, envir, RRuntime.LOGICAL_FALSE); } @Specialization @SuppressWarnings("unused") - protected Object getNonInherit(VirtualFrame frame, RAbstractStringVector x, Object value, REnvironment pos, RMissing envir, byte inherits, Object immediate) { - return assign.execute(frame, x, value, pos, inherits); + protected Object assign(String x, Object value, REnvironment pos, RMissing envir, byte inherits, Object immediate) { + return assign.execute(x, value, pos, inherits); } @Specialization @SuppressWarnings("unused") - protected Object getNonInherit(VirtualFrame frame, RAbstractStringVector x, Object value, REnvironment pos, RMissing envir, RMissing inherits, Object immediate) { - return assign.execute(frame, x, value, pos, RRuntime.LOGICAL_FALSE); + protected Object assign(String x, Object value, REnvironment pos, RMissing envir, RMissing inherits, Object immediate) { + return assign.execute(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/ExistsFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/ExistsFastPath.java index 981160811563d30307598e1f1e48eb4d53bc4f88..3d51162cc917617db971f90c59bbf7baf465e11d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/ExistsFastPath.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/ExistsFastPath.java @@ -33,6 +33,9 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RFastPathNode; +/** + * Avoids execution of the condition in default argument value of 'envir'. + */ public abstract class ExistsFastPath extends RFastPathNode { @Child private Exists exists = ExistsNodeGen.create(null); @@ -40,13 +43,13 @@ public abstract class ExistsFastPath extends RFastPathNode { @Specialization @SuppressWarnings("unused") protected Object fallback(RAbstractStringVector x, RMissing where, REnvironment envir, RMissing frame, RMissing mode, byte inherits) { - return exists.execute(x, envir, RType.Any.getName(), inherits); + return exists.execute(x.getDataAt(0), envir, RType.Any.getName(), RRuntime.fromLogical(inherits)); } @Specialization @SuppressWarnings("unused") protected Object fallback(RAbstractStringVector x, RMissing where, REnvironment envir, RMissing frame, RMissing mode, RMissing inherits) { - return exists.execute(x, envir, RType.Any.getName(), RRuntime.LOGICAL_TRUE); + return exists.execute(x.getDataAt(0), envir, RType.Any.getName(), true); } @Fallback diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/GetFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/GetFastPath.java index ae4330e44f577657e8a15197c759ed8f82ce7a5e..f8cd26d7715f22c50d2979a7f28e77dd63443893 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/GetFastPath.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/GetFastPath.java @@ -29,7 +29,6 @@ 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.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RFastPathNode; @@ -39,13 +38,13 @@ public abstract class GetFastPath extends RFastPathNode { @Specialization @SuppressWarnings("unused") - protected Object getNonInherit(VirtualFrame frame, RAbstractStringVector x, RMissing pos, REnvironment envir, RMissing mode, byte inherits) { + protected Object getNonInherit(VirtualFrame frame, String x, RMissing pos, REnvironment envir, RMissing mode, byte inherits) { return get.execute(frame, x, envir, "any", RRuntime.fromLogical(inherits)); } @Specialization @SuppressWarnings("unused") - protected Object getNonInherit(VirtualFrame frame, RAbstractStringVector x, RMissing pos, REnvironment envir, RMissing mode, RMissing inherits) { + protected Object getNonInherit(VirtualFrame frame, String x, RMissing pos, REnvironment envir, RMissing mode, RMissing inherits) { return get.execute(frame, x, envir, "any", true); } 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 395aa38443cccc09d4ac553cfe9a3329dca05f93..611cf68d898d0ed50f0630d15a1059eee1cf0174 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 @@ -32,45 +32,60 @@ import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.nodes.RFastPathNode; +import com.oracle.truffle.r.runtime.nodes.RNode; public abstract class IntersectFastPath extends RFastPathNode { - @Specialization(guards = {"x.getLength() > 0", "y.getLength() > 0"}) - protected RAbstractIntVector intersect(RAbstractIntVector x, RAbstractIntVector y, // - @Cached("createBinaryProfile()") ConditionProfile isXSortedProfile, // - @Cached("createBinaryProfile()") ConditionProfile isYSortedProfile, // + protected static final int TYPE_LIMIT = 2; + + 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) { - int xLength = x.getLength(); - int yLength = y.getLength(); - reportWork(xLength + yLength); + // apply the type profiles: + RAbstractIntVector profiledX = xClass.cast(x); + RAbstractIntVector profiledY = yClass.cast(y); + + int xLength = profiledX.getLength(); + int yLength = profiledY.getLength(); + RNode.reportWork(this, xLength + yLength); int count = 0; - int[] result = new int[Math.min(xLength, yLength)]; - if (isXSortedProfile.profile(isSorted(x))) { + int[] result = EMPTY_INT_ARRAY; + int maxResultLength = Math.min(xLength, yLength); + if (isXSortedProfile.profile(isSorted(profiledX))) { RAbstractIntVector tempY; - if (!isYSortedProfile.profile(isSorted(y))) { + if (isYSortedProfile.profile(isSorted(profiledY))) { + tempY = profiledY; + } else { int[] temp = new int[yLength]; for (int i = 0; i < yLength; i++) { - temp[i] = y.getDataAt(i); + temp[i] = profiledY.getDataAt(i); } sort(temp); - tempY = RDataFactory.createIntVector(temp, y.isComplete()); - } else { - tempY = y; + tempY = RDataFactory.createIntVector(temp, profiledY.isComplete()); } int xPos = 0; int yPos = 0; - int xValue = x.getDataAt(xPos); + int xValue = profiledX.getDataAt(xPos); int yValue = tempY.getDataAt(yPos); while (true) { if (xValue == yValue) { + if (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) { break; } - int nextValue = x.getDataAt(xPos + 1); + int nextValue = profiledX.getDataAt(xPos + 1); if (xValue != nextValue) { break; } @@ -80,13 +95,13 @@ public abstract class IntersectFastPath extends RFastPathNode { if (++xPos >= xLength || ++yPos >= yLength) { break; } - xValue = x.getDataAt(xPos); + xValue = profiledX.getDataAt(xPos); yValue = tempY.getDataAt(yPos); } else if (xValue < yValue) { if (++xPos >= xLength) { break; } - xValue = x.getDataAt(xPos); + xValue = profiledX.getDataAt(xPos); } else { if (++yPos >= yLength) { break; @@ -98,20 +113,23 @@ public abstract class IntersectFastPath extends RFastPathNode { int[] temp = new int[yLength]; boolean[] used = new boolean[yLength]; for (int i = 0; i < yLength; i++) { - temp[i] = y.getDataAt(i); + temp[i] = profiledY.getDataAt(i); } sort(temp); for (int i = 0; i < xLength; i++) { - int value = x.getDataAt(i); + int value = profiledX.getDataAt(i); int pos = Arrays.binarySearch(temp, value); if (pos >= 0 && !used[pos]) { used[pos] = true; + if (count >= result.length) { + result = Arrays.copyOf(result, Math.min(maxResultLength, Math.max(result.length * 2, 8))); + } result[count++] = value; } } } - return RDataFactory.createIntVector(resultLengthMatchProfile.profile(count == xLength) ? result : Arrays.copyOf(result, count), x.isComplete() | y.isComplete()); + return RDataFactory.createIntVector(resultLengthMatchProfile.profile(count == result.length) ? result : Arrays.copyOf(result, count), 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 19e6b1b609cf8b61fd8bb25aaa6198178b6a180b..63a1876788b7fe1d3456d3f6d7febe0c2bf550f5 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 @@ -28,7 +28,6 @@ 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.RRuntime; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RIntSequence; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -42,7 +41,6 @@ public abstract class IsElementFastPath extends RFastPathNode { protected Byte iselementOne(RAbstractStringVector el, RAbstractStringVector set, // @Cached("create()") BranchProfile trueProfile, // @Cached("create()") BranchProfile falseProfile) { - RContext.getInstance().setVisible(true); String element = el.getDataAt(0); int length = set.getLength(); for (int i = 0; i < length; i++) { @@ -57,7 +55,6 @@ public abstract class IsElementFastPath extends RFastPathNode { @Specialization protected Byte iselementOne(double el, double set) { - RContext.getInstance().setVisible(true); return RRuntime.asLogical(el == set); } @@ -65,7 +62,6 @@ public abstract class IsElementFastPath extends RFastPathNode { protected Byte iselementOne(RAbstractDoubleVector el, RAbstractDoubleVector set, // @Cached("create()") BranchProfile trueProfile, // @Cached("create()") BranchProfile falseProfile) { - RContext.getInstance().setVisible(true); double element = el.getDataAt(0); int length = set.getLength(); for (int i = 0; i < length; i++) { @@ -81,7 +77,6 @@ public abstract class IsElementFastPath extends RFastPathNode { @Specialization(guards = "el.getLength() == 1") protected Byte isElementOneSequence(RAbstractDoubleVector el, RIntSequence set, // @Cached("createBinaryProfile()") ConditionProfile profile) { - RContext.getInstance().setVisible(true); double element = el.getDataAt(0); return RRuntime.asLogical(profile.profile(element >= set.getStart() && element <= set.getEnd())); } @@ -91,7 +86,6 @@ public abstract class IsElementFastPath extends RFastPathNode { @Cached("create()") NACheck na, // @Cached("create()") BranchProfile trueProfile, // @Cached("create()") BranchProfile falseProfile) { - RContext.getInstance().setVisible(true); double element = el.getDataAt(0); int length = set.getLength(); na.enable(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 20017821af4533c0fe266a335d2bbb2d61fab069..8e30c4e9fad497addce28af9eee37b44e7ea7958 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 @@ -31,7 +31,6 @@ import com.oracle.truffle.r.nodes.builtin.base.MatrixNodeGen; import com.oracle.truffle.r.nodes.unary.CastIntegerNode; import com.oracle.truffle.r.nodes.unary.FirstIntNode; import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RRuntime; 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; @@ -62,7 +61,7 @@ public abstract class MatrixFastPath extends RFastPathNode { int row = rowMissing ? 1 : firstRow.executeInt(castRow.execute(nrow)); int col = colMissing ? 1 : firstCol.executeInt(castCol.execute(ncol)); Object dim = dimMissingProfile.profile(dimnames == RMissing.instance) ? RNull.instance : dimnames; - return matrix.execute(data, row, col, RRuntime.LOGICAL_FALSE, dim, RRuntime.asLogical(rowMissing), RRuntime.asLogical(colMissing)); + return matrix.execute(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/Dqrcf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java index b267d9521fcbcc765c10b5591a3e3bb734484085..b8dfa18b98a9656c6d2df0059a5589ebf7deda57 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 @@ -33,11 +33,11 @@ public final class Dqrcf extends RExternalBuiltinNode { Object[] argValues = args.getArguments(); try { RAbstractDoubleVector xVec = (RAbstractDoubleVector) argValues[0]; - int n = (int) argValues[1]; + int n = argValues[1] instanceof Integer ? (int) argValues[1] : ((RAbstractIntVector) argValues[1]).getDataAt(0); RAbstractIntVector k = (RAbstractIntVector) argValues[2]; RAbstractDoubleVector qrauxVec = (RAbstractDoubleVector) argValues[3]; RAbstractDoubleVector yVec = (RAbstractDoubleVector) argValues[4]; - int ny = (int) argValues[5]; + int ny = argValues[5] instanceof Integer ? (int) argValues[5] : ((RAbstractIntVector) argValues[5]).getDataAt(0); RAbstractDoubleVector bVec = (RAbstractDoubleVector) argValues[6]; RAbstractIntVector infoVec = (RAbstractIntVector) argValues[7]; double[] x = xVec.materialize().getDataTemp(); 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 0e8a93f22444ba6bb03f37a69de841eae38e05e4..fb842d465d81c176cdc1f5aeadaab8f3d07326c0 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 @@ -32,10 +32,10 @@ public final class Dqrdc2 extends RExternalBuiltinNode { Object[] argValues = args.getArguments(); try { RAbstractDoubleVector xVec = (RAbstractDoubleVector) argValues[0]; - int ldx = (int) argValues[1]; - int n = (int) argValues[2]; - int p = (int) argValues[3]; - double tol = (double) argValues[4]; + int ldx = argValues[1] instanceof Integer ? (int) argValues[1] : ((RAbstractIntVector) argValues[1]).getDataAt(0); + int n = argValues[2] instanceof Integer ? (int) argValues[2] : ((RAbstractIntVector) argValues[2]).getDataAt(0); + int p = argValues[3] instanceof Integer ? (int) argValues[3] : ((RAbstractIntVector) argValues[3]).getDataAt(0); + double tol = argValues[4] instanceof Double ? (double) argValues[4] : ((RAbstractDoubleVector) argValues[4]).getDataAt(0); RAbstractIntVector rankVec = (RAbstractIntVector) argValues[5]; RAbstractDoubleVector qrauxVec = (RAbstractDoubleVector) argValues[6]; RAbstractIntVector pivotVec = (RAbstractIntVector) argValues[7]; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java index 582337c61d1c2c1eff10889bcbff2597c3761af0..1b9e62e6a76dad2cb79ff9cfaed48f74f2432fbe 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java @@ -15,6 +15,7 @@ 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.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; @@ -45,6 +46,7 @@ import com.oracle.truffle.r.library.stats.Covcor; import com.oracle.truffle.r.library.stats.Dbinom; import com.oracle.truffle.r.library.stats.GammaFunctionsFactory.QgammaNodeGen; import com.oracle.truffle.r.library.stats.Pbinom; +import com.oracle.truffle.r.library.stats.Pf; import com.oracle.truffle.r.library.stats.Pnorm; import com.oracle.truffle.r.library.stats.Qbinom; import com.oracle.truffle.r.library.stats.Qnorm; @@ -66,8 +68,8 @@ import com.oracle.truffle.r.library.utils.Download; import com.oracle.truffle.r.library.utils.MenuNodeGen; import com.oracle.truffle.r.library.utils.ObjectSizeNodeGen; import com.oracle.truffle.r.library.utils.RprofNodeGen; +import com.oracle.truffle.r.library.utils.RprofmemNodeGen; import com.oracle.truffle.r.library.utils.TypeConvertNodeGen; -import com.oracle.truffle.r.library.utils.WriteTable; import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; @@ -146,7 +148,8 @@ public class ForeignFunctions { private static final String UNKNOWN_EXTERNAL_BUILTIN = "UNKNOWN_EXTERNAL_BUILTIN"; - protected String lookupName(RList f) { + protected static String lookupName(RList f) { + CompilerAsserts.neverPartOfCompilation(); if (f.getNames() != null) { RAbstractStringVector names = f.getNames(); for (int i = 0; i < names.getLength(); i++) { @@ -159,6 +162,7 @@ public class ForeignFunctions { return UNKNOWN_EXTERNAL_BUILTIN; } + @TruffleBoundary protected RuntimeException fallback(Object fobj) { String name = null; if (fobj instanceof RList) { @@ -284,6 +288,7 @@ public class ForeignFunctions { } @Override + @TruffleBoundary protected RExternalBuiltinNode lookupBuiltin(RList f) { String name = lookupName(f); switch (name) { @@ -364,6 +369,8 @@ public class ForeignFunctions { return RbinomNodeGen.create(); case "pbinom": return StatsFunctionsFactory.Function3_2NodeGen.create(new Pbinom()); + case "pf": + return StatsFunctionsFactory.Function3_2NodeGen.create(new Pf()); case "cutree": case "isoreg": case "monoFC_m": @@ -402,7 +409,6 @@ public class ForeignFunctions { case "binomial_dev_resids": case "rWishart": case "Cdist": - case "updateform": case "mvfft": case "nextn": case "r2dtable": @@ -444,8 +450,12 @@ public class ForeignFunctions { case "d2x2xk": return new UnimplementedExternal(name); + case "updateform": + return getExternalModelBuiltinNode("updateform"); + case "Cdqrls": return new RInternalCodeBuiltinNode(RContext.getInstance(), "stats", RInternalCode.loadSourceRelativeTo(StatsUtil.class, "lm.R"), "Cdqrls"); + case "dnorm": return StatsFunctionsFactory.Function3_1NodeGen.create(new Dnorm4()); @@ -550,6 +560,7 @@ public class ForeignFunctions { private final BranchProfile errorProfile = BranchProfile.create(); @Override + @TruffleBoundary protected RExternalBuiltinNode lookupBuiltin(RList f) { String name = lookupName(f); if (FastROptions.UseInternalGraphics.getBooleanValue()) { @@ -576,8 +587,9 @@ public class ForeignFunctions { return getExternalModelBuiltinNode("termsform"); case "Rprof": return RprofNodeGen.create(); - case "unzip": case "Rprofmem": + return RprofmemNodeGen.create(); + case "unzip": case "addhistory": case "loadhistory": case "savehistory": @@ -639,6 +651,7 @@ public class ForeignFunctions { private final BranchProfile errorProfile = BranchProfile.create(); @Override + @TruffleBoundary protected RExternalBuiltinNode lookupBuiltin(RList f) { if (FastROptions.UseInternalGraphics.getBooleanValue()) { switch (lookupName(f)) { @@ -709,6 +722,7 @@ public class ForeignFunctions { private final BranchProfile errorProfile = BranchProfile.create(); @Override + @TruffleBoundary protected RExternalBuiltinNode lookupBuiltin(RList f) { if (FastROptions.UseInternalGraphics.getBooleanValue()) { switch (lookupName(f)) { @@ -770,6 +784,7 @@ public class ForeignFunctions { } @Override + @TruffleBoundary protected RExternalBuiltinNode lookupBuiltin(RList f) { switch (lookupName(f)) { default: @@ -796,6 +811,7 @@ public class ForeignFunctions { } @Specialization + @TruffleBoundary protected Object callNamedFunctionWithPackage(String name, RArgsValuesAndNames args, String packageName) { DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.Call, null, null); long func = DLL.findSymbol(name, packageName, rns); 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 0951f5d262ecc3f0d879403229b3668bf86d805d..876a634a898fc79131865337c7aa9473141ba39d 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 @@ -13,6 +13,7 @@ package com.oracle.truffle.r.nodes.builtin.base.foreign; import java.io.IOException; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.conn.RConnection; @@ -22,6 +23,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; public final class ReadTableHead extends RExternalBuiltinNode { @Override + @TruffleBoundary public Object call(RArgsValuesAndNames args) { // TODO This is quite incomplete and just uses readLines, which works for some inputs Object[] argValues = args.getArguments(); diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/WriteTable.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java similarity index 89% rename from com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/WriteTable.java rename to com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java index 7ad8d59c6523823ea33ddd8c0e109eee6aa3db3a..0ecf5afe88050f58b605bd30874151ae7e046d87 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/WriteTable.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java @@ -9,13 +9,14 @@ * * All rights reserved. */ -package com.oracle.truffle.r.library.utils; +package com.oracle.truffle.r.nodes.builtin.base.foreign; import java.io.IOException; -import java.io.OutputStream; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; 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.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; @@ -45,15 +46,14 @@ public final class WriteTable extends RExternalBuiltinNode { @TruffleBoundary private static Object execute(RConnection con, Object xx, int nr, int nc, Object rnames, String csep, String ceol, String cna, char cdec, boolean qmethod, boolean[] quoteCol, boolean quoteRn) throws IOException, IllegalArgumentException { - OutputStream os = con.getOutputStream(); String tmp = null; if (RRuntime.hasRClass(xx, RRuntime.CLASS_DATA_FRAME)) { - executeDataFrame(os, (RVector) xx, nr, nc, rnames, csep, ceol, cna, cdec, qmethod, quoteCol, quoteRn); + executeDataFrame(con, (RVector<?>) xx, nr, nc, rnames, csep, ceol, cna, cdec, qmethod, quoteCol, quoteRn); } else { /* A matrix */ // if (!isVectorAtomic(x)) // UNIMPLEMENTED_TYPE("write.table, matrix method", x); - RVector x = (RVector) xx; + RVector<?> x = (RVector<?>) xx; /* quick integrity check */ if (x.getLength() != nr * nc) { throw new IllegalArgumentException("corrupt matrix -- dims not not match length"); @@ -64,11 +64,12 @@ public final class WriteTable extends RExternalBuiltinNode { // R_CheckUserInterrupt(); } if (!(rnames instanceof RNull)) { - os.write(new StringBuffer(encodeElement2((RStringVector) rnames, i, quoteRn, qmethod, cdec)).append(csep).toString().getBytes()); + con.writeString(encodeElement2((RStringVector) rnames, i, quoteRn, qmethod, cdec), false); + con.writeString(csep, false); } for (int j = 0; j < nc; j++) { if (j > 0) { - os.write(csep.getBytes()); + con.writeString(csep, false); } if (isna(x, i + j * nr)) { tmp = cna; @@ -76,16 +77,16 @@ public final class WriteTable extends RExternalBuiltinNode { tmp = encodeElement2(x, i + j * nr, quoteCol[j], qmethod, cdec); /* if(cdec) change_dec(tmp, cdec, TYPEOF(x)); */ } - os.write(tmp.getBytes()); + con.writeString(tmp, false); } - os.write(ceol.getBytes()); + con.writeString(ceol, false); } } return RNull.instance; } - private static void executeDataFrame(OutputStream os, RVector x, int nr, int nc, Object rnames, String csep, String ceol, String cna, char cdec, boolean qmethod, boolean[] quoteCol, + private static void executeDataFrame(RConnection con, RVector<?> x, int nr, int nc, Object rnames, String csep, String ceol, String cna, char cdec, boolean qmethod, boolean[] quoteCol, boolean quoteRn) throws IOException { String tmp; @@ -114,12 +115,12 @@ public final class WriteTable extends RExternalBuiltinNode { // R_CheckUserInterrupt(); if (!(rnames instanceof RNull)) { tmp = new StringBuffer(encodeElement2((RStringVector) rnames, i, quoteRn, qmethod, cdec)).append(csep).toString(); - os.write(tmp.getBytes()); + con.writeString(tmp, false); } for (int j = 0; j < nc; j++) { Object xjObj = x.getDataAtAsObject(j); if (j > 0) { - os.write(csep.getBytes()); + con.writeString(csep, false); } if (xjObj instanceof RAbstractContainer) { RAbstractContainer xj = (RAbstractContainer) xjObj; @@ -137,9 +138,9 @@ public final class WriteTable extends RExternalBuiltinNode { tmp = encodePrimitiveElement(xjObj, cna, quoteRn, qmethod); /* if(cdec) change_dec(tmp, cdec, TYPEOF(xj)); */ } - os.write(tmp.getBytes()); + con.writeString(tmp, false); } - os.write(ceol.getBytes()); + con.writeString(ceol, false); } } @@ -179,7 +180,7 @@ public final class WriteTable extends RExternalBuiltinNode { return RRuntime.isNA(v) ? cna : RRuntime.intToStringNoCheck(v); } else if (o instanceof Double) { double v = (double) o; - return RRuntime.isNA(v) ? cna : RRuntime.doubleToStringNoCheck(v); + return RRuntime.isNA(v) ? cna : DoubleVectorPrinter.encodeReal(v); } else if (o instanceof Byte) { byte v = (byte) o; return RRuntime.isNA(v) ? cna : RRuntime.logicalToStringNoCheck(v); @@ -188,10 +189,10 @@ public final class WriteTable extends RExternalBuiltinNode { return RRuntime.isNA(v) ? cna : encodeStringElement(v, quote, qmethod); } else if (o instanceof Double) { RComplex v = (RComplex) o; - return RRuntime.isNA(v) ? cna : RRuntime.complexToStringNoCheck(v); + return RRuntime.isNA(v) ? cna : ComplexVectorPrinter.encodeComplex(v); } else if (o instanceof RRaw) { RRaw v = (RRaw) o; - return RRuntime.rawToString(v); + return RRuntime.rawToHexString(v); } throw RInternalError.unimplemented(); } @@ -218,7 +219,7 @@ public final class WriteTable extends RExternalBuiltinNode { private static String encodeElement(Object x, int indx, char quote, char dec) { if (x instanceof RAbstractDoubleVector) { RAbstractDoubleVector v = (RAbstractDoubleVector) x; - return RRuntime.doubleToString(v.getDataAt(indx)); + return DoubleVectorPrinter.encodeReal(v.getDataAt(indx)); } if (x instanceof RAbstractIntVector) { RAbstractIntVector v = (RAbstractIntVector) x; @@ -230,11 +231,11 @@ public final class WriteTable extends RExternalBuiltinNode { } if (x instanceof RAbstractComplexVector) { RAbstractComplexVector v = (RAbstractComplexVector) x; - return RRuntime.complexToString(v.getDataAt(indx)); + return ComplexVectorPrinter.encodeComplex(v.getDataAt(indx)); } if (x instanceof RAbstractRawVector) { RAbstractRawVector v = (RAbstractRawVector) x; - return RRuntime.rawToString(v.getDataAt(indx)); + return RRuntime.rawToHexString(v.getDataAt(indx)); } throw RInternalError.unimplemented(); } @@ -254,6 +255,7 @@ public final class WriteTable extends RExternalBuiltinNode { } // Transcribed from GnuR, library/utils/src/io.c + @TruffleBoundary @Override public Object call(RArgsValuesAndNames args) { Object[] argValues = args.getArguments(); 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 new file mode 100644 index 0000000000000000000000000000000000000000..745163d03ce12e4b742231cbe00dfe54ed70e951 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java @@ -0,0 +1,128 @@ +/* + * 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.builtin.base.infix; + +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; +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.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +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.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; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +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.RType; +import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.builtins.RSpecialFactory; +import com.oracle.truffle.r.runtime.data.RList; +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; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.nodes.RNode; + +@TypeSystemReference(EmptyTypeSystemFlatLayout.class) +@NodeChild(value = "arguments", type = RNode[].class) +abstract class AccessFieldSpecial extends RNode { + + @CompilationFinal String cachedField; + @CompilationFinal RStringVector cachedNames; + @Child private ExtractListElement extractListElement = ExtractListElement.create(); + + @Specialization(guards = {"isCached(list, field)", "list.getNames() != null"}) + @SuppressWarnings("unused") + public Object doList(RList list, String field, @Cached("getIndex(list.getNames(), field)") int index) { + if (index == -1) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + throw RSpecialFactory.FULL_CALL_NEEDED; + } + if (cachedField == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + cachedField = field; + cachedNames = list.getNames(); + } + return extractListElement.execute(list, index); + } + + @Fallback + @SuppressWarnings("unused") + public void doFallback(Object container, Object field) { + throw RSpecialFactory.FULL_CALL_NEEDED; + } + + protected boolean isCached(RList list, String field) { + return cachedField == null || (cachedField == field && list.getNames() == cachedNames); + } + + protected int getIndex(RAbstractStringVector names, String field) { + for (int i = 0; i < names.getLength(); i++) { + String current = names.getDataAt(i); + if (current == field || current.equals(field)) { + return i; + } + } + return -1; + } +} + +@RBuiltin(name = "$", kind = PRIMITIVE, parameterNames = {"", ""}, dispatch = INTERNAL_GENERIC, behavior = PURE) +public abstract class AccessField extends RBuiltinNode { + + @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + + private final ConditionProfile invalidAtomicVector = ConditionProfile.createBinaryProfile(); + private final BranchProfile error = BranchProfile.create(); + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg(1).defaultError(Message.INVALID_SUBSCRIPT_TYPE, RType.Language.getName()).mustBe(stringValue()).asStringVector().findFirst(); + } + + public static RNode createSpecial(ArgumentsSignature signature, RNode[] arguments) { + return signature.getNonNullCount() == 0 ? AccessFieldSpecialNodeGen.create(arguments) : null; + } + + @Specialization + 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); + } + return extract.applyAccessField(frame, container, field); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..0af31a87568f97662b715ea3ea2cc3bd3984b762 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltin.java @@ -0,0 +1,41 @@ +/* + * 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.builtin.base.infix; + +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.RInternalError; +import com.oracle.truffle.r.runtime.RVisibility; +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 { + @SuppressWarnings("unused") + @Specialization + protected Object doIt(Object x, 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 new file mode 100644 index 0000000000000000000000000000000000000000..95885e8a30e140035c60acd02d82af57ec80a8a7 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltinEq.java @@ -0,0 +1,41 @@ +/* + * 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.builtin.base.infix; + +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.RInternalError; +import com.oracle.truffle.r.runtime.RVisibility; +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 { + @SuppressWarnings("unused") + @Specialization + protected Object doIt(Object x, 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 new file mode 100644 index 0000000000000000000000000000000000000000..3e77803457c58a3b68035474e52d27c0054f6e49 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignOuterBuiltin.java @@ -0,0 +1,41 @@ +/* + * 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.builtin.base.infix; + +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 com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.RInternalError; +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 { + @SuppressWarnings("unused") + @Specialization + protected Object doIt(Object x, 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 new file mode 100644 index 0000000000000000000000000000000000000000..8f16de33a5ca16e9e182d07f0d22825ae99cfc06 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BraceBuiltin.java @@ -0,0 +1,41 @@ +/* + * 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.builtin.base.infix; + +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; + +import com.oracle.truffle.api.dsl.Specialization; +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 = "{", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) +public abstract class BraceBuiltin extends RBuiltinNode { + @SuppressWarnings("unused") + @Specialization + protected Object doIt(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 new file mode 100644 index 0000000000000000000000000000000000000000..01f7da077754737f1d0db909b9d2c5868026fe5a --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BreakBuiltin.java @@ -0,0 +1,40 @@ +/* + * 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.builtin.base.infix; + +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 com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +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 { + @SuppressWarnings("unused") + @Specialization + protected Object doIt(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 new file mode 100644 index 0000000000000000000000000000000000000000..3f73a57513005f5fba456f7c5cb8bd7c86c65b4e --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ForBuiltin.java @@ -0,0 +1,41 @@ +/* + * 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.builtin.base.infix; + +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; + +import com.oracle.truffle.api.dsl.Specialization; +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 = "for", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) +public abstract class ForBuiltin extends RBuiltinNode { + @SuppressWarnings("unused") + @Specialization + protected Object doIt(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 new file mode 100644 index 0000000000000000000000000000000000000000..8cff9b6229b75dfb53bc83565fa8ac1c8a4762ad --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java @@ -0,0 +1,40 @@ +/* + * 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.builtin.base.infix; + +import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_FRAME; +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.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 { + @SuppressWarnings("unused") + @Specialization + protected Object doIt(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 new file mode 100644 index 0000000000000000000000000000000000000000..fa86a26fed9099b43264b70447ccf4a05b2e9b8a --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/IfBuiltin.java @@ -0,0 +1,41 @@ +/* + * 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.builtin.base.infix; + +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; + +import com.oracle.truffle.api.dsl.Specialization; +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 = "if", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) +public abstract class IfBuiltin extends RBuiltinNode { + @SuppressWarnings("unused") + @Specialization + protected Object doIt(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 new file mode 100644 index 0000000000000000000000000000000000000000..b26ceb62690aa9016ec6dde9c9380820d2a511ab --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java @@ -0,0 +1,40 @@ +/* + * 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.builtin.base.infix; + +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 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 { + @SuppressWarnings("unused") + @Specialization + protected Object doIt(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 new file mode 100644 index 0000000000000000000000000000000000000000..23c4c9cbf938de9aa25c65137c0498499e9cb009 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java @@ -0,0 +1,40 @@ +/* + * 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.builtin.base.infix; + +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.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.builtins.RBuiltin; + +@RBuiltin(name = "(", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) +public abstract class ParenBuiltin extends RBuiltinNode { + @SuppressWarnings("unused") + @Specialization + protected Object doIt(Object x) { + throw RInternalError.unimplemented(); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..457a84b43eaad8023f769941eeeb642fec26fe59 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/RepeatBuiltin.java @@ -0,0 +1,41 @@ +/* + * 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.builtin.base.infix; + +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; + +import com.oracle.truffle.api.dsl.Specialization; +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 = "repeat", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) +public abstract class RepeatBuiltin extends RBuiltinNode { + @SuppressWarnings("unused") + @Specialization + protected Object doIt(Object x) { + throw RInternalError.unimplemented(); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..6691aeb71c2c7875af8376e004646c89bc772cbb --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java @@ -0,0 +1,173 @@ +/* + * 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.builtin.base.infix; + +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.frame.VirtualFrame; +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.function.ClassHierarchyNode; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; +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.RRuntime; +import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +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.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 com.oracle.truffle.r.runtime.nodes.RNode; + +@NodeChild(value = "arguments", type = RNode[].class) +abstract class SubscriptSpecial extends RNode { + + @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false); + + protected boolean simpleVector(RAbstractVector vector) { + return classHierarchy.execute(vector) == null; + } + + protected static boolean inIntRange(RAbstractVector vector, int index) { + return index >= 1 && index <= vector.getLength(); + } + + protected static boolean inDoubleRange(RAbstractVector vector, double index) { + return index > 0 && index < (vector.getLength() + 1); + } + + private static int toInt(double index) { + int i = (int) index; + return i == 0 ? 1 : i - 1; + } + + @Specialization(guards = {"simpleVector(vector)", "inIntRange(vector, index)"}) + protected static int access(RAbstractIntVector vector, int index) { + return vector.getDataAt(index - 1); + } + + @Specialization(guards = {"simpleVector(vector)", "inIntRange(vector, index)"}) + protected static double access(RAbstractDoubleVector vector, int index) { + return vector.getDataAt(index - 1); + } + + @Specialization(guards = {"simpleVector(vector)", "inIntRange(vector, index)"}) + protected static String access(RAbstractStringVector vector, int index) { + return vector.getDataAt(index - 1); + } + + @Specialization(guards = {"simpleVector(vector)", "inIntRange(vector, index)"}) + protected static Object access(RList vector, int index, + @Cached("create()") ExtractListElement extract) { + return extract.execute(vector, index - 1); + } + + @Specialization(guards = {"simpleVector(vector)", "inDoubleRange(vector, index)"}) + protected static int access(RAbstractIntVector vector, double index) { + return vector.getDataAt(toInt(index)); + } + + @Specialization(guards = {"simpleVector(vector)", "inDoubleRange(vector, index)"}) + protected static double access(RAbstractDoubleVector vector, double index) { + return vector.getDataAt(toInt(index)); + } + + @Specialization(guards = {"simpleVector(vector)", "inDoubleRange(vector, index)"}) + protected static String access(RAbstractStringVector vector, double index) { + return vector.getDataAt(toInt(index)); + } + + @Specialization(guards = {"simpleVector(vector)", "inDoubleRange(vector, index)"}) + protected static Object access(RList vector, double index, + @Cached("create()") ExtractListElement extract) { + return extract.execute(vector, toInt(index)); + } + + @SuppressWarnings("unused") + @Fallback + protected Object access(Object vector, Object index) { + throw RCallSpecialNode.fullCallNeeded(); + } +} + +@RBuiltin(name = "[[", kind = PRIMITIVE, parameterNames = {"", "...", "exact", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE) +public abstract class Subscript extends RBuiltinNode { + + @RBuiltin(name = ".subset2", kind = PRIMITIVE, parameterNames = {"x", "...", "exact", "drop"}, behavior = PURE) + public abstract class DefaultBuiltin { + // same implementation as "[[", with different dispatch + } + + public static RNode special(ArgumentsSignature signature, RNode[] arguments) { + return signature.getNonNullCount() == 0 && arguments.length == 2 ? SubscriptSpecialNodeGen.create(arguments) : null; + } + + @Child private ExtractVectorNode extractNode = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, false); + + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{RMissing.instance, RArgsValuesAndNames.EMPTY, RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_TRUE}; + } + + @SuppressWarnings("unused") + @Specialization + protected RNull getNoInd(RNull x, Object inds, Object exactVec, Object drop) { + return x; + } + + @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); + } + + @SuppressWarnings("unused") + @Specialization + protected Object get(Object x, RMissing indexes, RAbstractLogicalVector exact, RAbstractLogicalVector drop) { + throw RError.error(this, RError.Message.NO_INDEX); + } + + @Specialization(guards = "!indexes.isEmpty()") + protected Object get(VirtualFrame frame, Object x, RArgsValuesAndNames indexes, RAbstractLogicalVector exact, @SuppressWarnings("unused") Object drop) { + /* + * "drop" is not actually used by this builtin, but it needs to be in the argument list + * (because the "drop" argument needs to be skipped). + */ + return extractNode.apply(frame, x, indexes.getArguments(), exact, RLogical.TRUE); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..e28516acb8a29bd3f9b25596c665088cd00398d3 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java @@ -0,0 +1,171 @@ +/* + * 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.builtin.base.infix; + +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.frame.VirtualFrame; +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.CastBuilder; +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.RCallSpecialNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RAttributeProfiles; +import com.oracle.truffle.r.runtime.data.RDataFactory; +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.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.nodes.RNode; + +@NodeChild(value = "arguments", type = RNode[].class) +abstract class SubsetSpecial extends RNode { + + @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false); + + private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + + protected boolean simpleVector(RAbstractVector vector) { + return classHierarchy.execute(vector) == null && vector.getNames(attrProfiles) == null; + } + + protected static boolean inIntRange(RAbstractVector vector, int index) { + return index >= 1 && index <= vector.getLength(); + } + + protected static boolean inDoubleRange(RAbstractVector vector, double index) { + return index >= 1 && index <= vector.getLength(); + } + + private static int toInt(double index) { + int i = (int) index; + return i == 0 ? 1 : i - 1; + } + + @Specialization(guards = {"simpleVector(vector)", "inIntRange(vector, index)"}) + protected static int access(RAbstractIntVector vector, int index) { + return vector.getDataAt(index - 1); + } + + @Specialization(guards = {"simpleVector(vector)", "inIntRange(vector, index)"}) + protected static double access(RAbstractDoubleVector vector, int index) { + return vector.getDataAt(index - 1); + } + + @Specialization(guards = {"simpleVector(vector)", "inIntRange(vector, index)"}) + protected static String access(RAbstractStringVector vector, int index) { + return vector.getDataAt(index - 1); + } + + @Specialization(guards = {"simpleVector(vector)", "inIntRange(vector, index)"}) + protected static RList access(RList vector, int index, + @Cached("create()") ExtractListElement extract) { + return RDataFactory.createList(new Object[]{extract.execute(vector, index - 1)}); + } + + @Specialization(guards = {"simpleVector(vector)", "inDoubleRange(vector, index)"}) + protected static int access(RAbstractIntVector vector, double index) { + return vector.getDataAt(toInt(index)); + } + + @Specialization(guards = {"simpleVector(vector)", "inDoubleRange(vector, index)"}) + protected static double access(RAbstractDoubleVector vector, double index) { + return vector.getDataAt(toInt(index)); + } + + @Specialization(guards = {"simpleVector(vector)", "inDoubleRange(vector, index)"}) + protected static String access(RAbstractStringVector vector, double index) { + return vector.getDataAt(toInt(index)); + } + + @Specialization(guards = {"simpleVector(vector)", "inDoubleRange(vector, index)"}) + protected static RList access(RList vector, double index, + @Cached("create()") ExtractListElement extract) { + return RDataFactory.createList(new Object[]{extract.execute(vector, toInt(index))}); + } + + @SuppressWarnings("unused") + @Fallback + protected static Object access(Object vector, Object index) { + throw RCallSpecialNode.fullCallNeeded(); + } +} + +@RBuiltin(name = "[", kind = PRIMITIVE, parameterNames = {"x", "...", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE) +public abstract class Subset extends RBuiltinNode { + + @RBuiltin(name = ".subset", kind = PRIMITIVE, parameterNames = {"", "...", "drop"}, behavior = PURE) + public abstract class DefaultBuiltin { + // same implementation as "[", with different dispatch + } + + public static RNode special(ArgumentsSignature signature, RNode[] arguments) { + return signature.getNonNullCount() == 0 && arguments.length == 2 ? SubsetSpecialNodeGen.create(arguments) : null; + } + + @Child private ExtractVectorNode extractNode = ExtractVectorNode.create(ElementAccessMode.SUBSET, false); + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("drop").asLogicalVector(); + } + + @SuppressWarnings("unused") + @Specialization + protected RNull get(RNull x, Object indexes, Object drop) { + return x; + } + + @SuppressWarnings("unused") + @Specialization(guards = "indexes.isEmpty()") + protected Object getNoInd(Object x, RArgsValuesAndNames indexes, Object drop) { + return x; + } + + @SuppressWarnings("unused") + @Specialization + protected Object get(Object x, RMissing indexes, Object drop) { + return x; + } + + @Specialization(guards = "!indexes.isEmpty()") + protected Object get(VirtualFrame frame, Object x, RArgsValuesAndNames indexes, Object drop) { + return extractNode.apply(frame, x, indexes.getArguments(), RLogical.TRUE, drop); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..771bc4bd590e1e2d170aacb2159ceca8c77d16c5 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java @@ -0,0 +1,66 @@ +/* + * 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.builtin.base.infix; + +import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_FRAME; +import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; + +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.function.RCallNode; +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.RLanguage; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; + +/** + * This a rather strange function. It is where, in GnuR, that the "formula" class is set and the + * ".Environment" attribute on the "call". N.B. the "response" can be missing, which is actually + * handled by an evaluated argument of type {@link RMissing}, although it appears as if the "model" + * argument is missing, i.e. {@code ~ x} result in {@code `~`(x)}. + */ +@RBuiltin(name = "~", kind = PRIMITIVE, parameterNames = {"x", "y"}, nonEvalArgs = {0, 1}, behavior = READS_FRAME) +public abstract class Tilde extends RBuiltinNode { + + private static final RStringVector FORMULA_CLASS = RDataFactory.createStringVectorFromScalar(RRuntime.FORMULA_CLASS); + + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{RMissing.instance, RMissing.instance}; + } + + @Specialization + protected RLanguage tilde(VirtualFrame frame, @SuppressWarnings("unused") Object response, @SuppressWarnings("unused") Object model) { + RCallNode call = (RCallNode) ((RBaseNode) getParent()).asRSyntaxNode(); + RLanguage lang = RDataFactory.createLanguage(call); + lang.setClassAttr(FORMULA_CLASS); + REnvironment env = REnvironment.frameToEnvironment(frame.materialize()); + lang.setAttr(RRuntime.DOT_ENVIRONMENT, env); + return lang; + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..11f19dfcf2da4bd81ed1799481b40c71c48341ef --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java @@ -0,0 +1,76 @@ +/* + * 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.builtin.base.infix; + +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; +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.CompilerDirectives; +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.vector.ElementAccessMode; +import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.unary.CastListNode; +import com.oracle.truffle.r.nodes.unary.CastListNodeGen; +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.model.RAbstractListVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +@RBuiltin(name = "$<-", kind = PRIMITIVE, parameterNames = {"", "", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE) +public abstract class UpdateField extends RBuiltinNode { + + @Child private ReplaceVectorNode extract = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + @Child private CastListNode castList; + + private final ConditionProfile coerceList = ConditionProfile.createBinaryProfile(); + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg(1).defaultError(Message.INVALID_SUBSCRIPT).mustBe(stringValue()).asStringVector().findFirst(); + } + + @Specialization + protected Object update(VirtualFrame frame, Object container, String field, Object value) { + Object list = coerceList.profile(container instanceof RAbstractListVector) ? container : coerceList(container); + return extract.apply(frame, list, new Object[]{field}, value); + } + + private Object coerceList(Object vector) { + if (vector instanceof RAbstractVector) { + if (castList == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + castList = insert(CastListNodeGen.create(true, true, false)); + } + RError.warning(this, 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 new file mode 100644 index 0000000000000000000000000000000000000000..abae6d456fa6566e628f29e2ff3d06c169aaa80f --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java @@ -0,0 +1,66 @@ +/* + * 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.builtin.base.infix; + +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 java.util.Arrays; + +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.vector.ElementAccessMode; +import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode; +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.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RMissing; + +@RBuiltin(name = "[[<-", kind = PRIMITIVE, parameterNames = {"", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE) +public abstract class UpdateSubscript extends RBuiltinNode { + + @Child private ReplaceVectorNode replaceNode = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, false); + + private final ConditionProfile argsLengthLargerThanOneProfile = ConditionProfile.createBinaryProfile(); + + @Specialization(guards = "!args.isEmpty()") + protected Object update(VirtualFrame frame, Object x, RArgsValuesAndNames args) { + Object value = args.getArgument(args.getLength() - 1); + Object[] pos; + if (argsLengthLargerThanOneProfile.profile(args.getLength() > 1)) { + pos = Arrays.copyOf(args.getArguments(), args.getLength() - 1); + } else { + pos = new Object[]{RMissing.instance}; + } + return replaceNode.apply(frame, x, pos, value); + } + + @Specialization(guards = "args.isEmpty()") + @SuppressWarnings("unused") + protected Object getNoInd(Object x, RArgsValuesAndNames args) { + throw RError.error(this, 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 new file mode 100644 index 0000000000000000000000000000000000000000..ca2ed744a44e6332c5d865df285cafd100127dd9 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java @@ -0,0 +1,172 @@ +/* + * 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.builtin.base.infix; + +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 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.NodeChild; +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.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.function.ClassHierarchyNode; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; +import com.oracle.truffle.r.nodes.function.RCallSpecialNode; +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.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +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.RMissing; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.ops.na.NACheck; + +@NodeChild(value = "arguments", type = RNode[].class) +abstract class UpdateSubsetSpecial extends RNode { + @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 static boolean inIntRange(RAbstractVector vector, int index) { + return index >= 1 && index <= vector.getLength(); + } + + protected static boolean inDoubleRange(RAbstractVector vector, double index) { + return index > 0 && index < (vector.getLength() + 1); + } + + private static int toInt(double index) { + int i = (int) index; + return i == 0 ? 1 : i - 1; + } + + @Specialization(guards = {"simple(vector)", "!vector.isShared()", "inIntRange(vector, index)"}) + protected RIntVector access(RIntVector vector, int index, int value) { + return vector.updateDataAt(index - 1, value, naCheck); + } + + @Specialization(guards = {"simple(vector)", "!vector.isShared()", "inIntRange(vector, index)"}) + protected RDoubleVector access(RDoubleVector vector, int index, double value) { + return vector.updateDataAt(index - 1, value, naCheck); + } + + @Specialization(guards = {"simple(vector)", "!vector.isShared()", "inIntRange(vector, index)"}) + protected RStringVector access(RStringVector vector, int index, String value) { + return vector.updateDataAt(index - 1, value, naCheck); + } + + @Specialization(guards = {"simple(list)", "!list.isShared()", "inIntRange(list, index)"}) + protected static Object access(RList list, int index, Object value, + @Cached("create()") ShareObjectNode shareObject) { + if (value instanceof RNull) { + CompilerDirectives.transferToInterpreter(); + throw RCallSpecialNode.fullCallNeeded(); + } + list.setDataAt(list.getInternalStore(), index - 1, shareObject.execute(value)); + return list; + } + + @Specialization(guards = {"simple(vector)", "!vector.isShared()", "inDoubleRange(vector, index)"}) + protected RIntVector accessDoubleIndex(RIntVector vector, double index, int value) { + return vector.updateDataAt(toInt(index), value, naCheck); + } + + @Specialization(guards = {"simple(vector)", "!vector.isShared()", "inDoubleRange(vector, index)"}) + protected RDoubleVector accessDoubleIndex(RDoubleVector vector, double index, double value) { + return vector.updateDataAt(toInt(index), value, naCheck); + } + + @Specialization(guards = {"simple(vector)", "!vector.isShared()", "inDoubleRange(vector, index)"}) + protected RStringVector accessDoubleIndex(RStringVector vector, double index, String value) { + return vector.updateDataAt(toInt(index), value, naCheck); + } + + @Specialization(guards = {"simple(list)", "!list.isShared()", "inDoubleRange(list, index)"}) + protected static Object accessDoubleIndex(RList list, double index, Object value, + @Cached("create()") ShareObjectNode shareObject) { + if (value instanceof RNull) { + CompilerDirectives.transferToInterpreter(); + throw RCallSpecialNode.fullCallNeeded(); + } + list.setDataAt(list.getInternalStore(), toInt(index), shareObject.execute(value)); + return list; + } + + @SuppressWarnings("unused") + @Fallback + protected Object access(Object vector, Object index, Object value) { + throw RCallSpecialNode.fullCallNeeded(); + } +} + +@RBuiltin(name = "[<-", kind = PRIMITIVE, parameterNames = {"", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE) +public abstract class UpdateSubset extends RBuiltinNode { + + private static final String valueArgName = "value".intern(); + + @Child private ReplaceVectorNode replaceNode = ReplaceVectorNode.create(ElementAccessMode.SUBSET, false); + private final ConditionProfile argsLengthLargerThanOneProfile = ConditionProfile.createBinaryProfile(); + + @SuppressWarnings("StringEquality") + public static RNode special(ArgumentsSignature signature, RNode[] arguments) { + // Note: the signature names should be interned, the '!=' is intended + boolean hasCorrectSignature = signature.getLength() != 3 || signature.getName(0) != null || signature.getName(1) != null || signature.getName(2) != valueArgName; + return hasCorrectSignature && arguments.length == 3 ? UpdateSubsetSpecialNodeGen.create(arguments) : null; + } + + @Specialization(guards = "!args.isEmpty()") + protected Object update(VirtualFrame frame, Object x, RArgsValuesAndNames args) { + Object value = args.getArgument(args.getLength() - 1); + Object[] pos; + if (argsLengthLargerThanOneProfile.profile(args.getLength() > 1)) { + pos = Arrays.copyOf(args.getArguments(), args.getLength() - 1); + } else { + pos = new Object[]{RMissing.instance}; + } + return replaceNode.apply(frame, x, pos, value); + } + + @Specialization(guards = "args.isEmpty()") + @SuppressWarnings("unused") + protected Object getNoInd(Object x, RArgsValuesAndNames args) { + throw RError.error(this, 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 new file mode 100644 index 0000000000000000000000000000000000000000..9512dd07b558e46252f01859656fa879f34015c6 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/WhileBuiltin.java @@ -0,0 +1,41 @@ +/* + * 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.builtin.base.infix; + +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; + +import com.oracle.truffle.api.dsl.Specialization; +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 = "while", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) +public abstract class WhileBuiltin extends RBuiltinNode { + @SuppressWarnings("unused") + @Specialization + protected Object doIt(Object x) { + throw RInternalError.unimplemented(); + } +} 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 6b0750ff92b1eea5ac6db59c0df824e136b4212c..e77aaf5b1da3818987d3111ba7a651b0e6f3dc33 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 @@ -15,6 +15,7 @@ package com.oracle.truffle.r.nodes.builtin.base.printer; import java.io.IOException; import java.io.PrintWriter; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributable; @@ -34,6 +35,7 @@ final class AttributesPrinter implements ValuePrinter<RAttributable> { } @Override + @TruffleBoundary public void print(RAttributable value, PrintContext printCtx) throws IOException { RAttributes attrs = value.getAttributes(); if (attrs == null) { @@ -52,7 +54,7 @@ final class AttributesPrinter implements ValuePrinter<RAttributable> { continue; } } - if (utils.inherits(value, "factor", RRuntime.LOGICAL_FALSE)) { + if (utils.inherits(value, RRuntime.CLASS_FACTOR)) { if (RRuntime.LEVELS_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 de21a6ad6ef960ed690fd934ee6829ddec661c06..15352ca9f5bdfa85d3835edf7446cacc1f9352bd 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 @@ -16,6 +16,7 @@ import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.snprintf; import java.io.IOException; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.nodes.builtin.base.Round; import com.oracle.truffle.r.nodes.builtin.base.Round.RoundArithmetic; import com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorPrinter.ScientificDouble; @@ -25,7 +26,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; //Transcribed from GnuR, src/main/printutils.c -final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVector> { +public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVector> { static final ComplexVectorPrinter INSTANCE = new ComplexVectorPrinter(); @@ -72,7 +73,13 @@ final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVector> { } } + @TruffleBoundary static ComplexVectorMetrics formatComplexVector(RAbstractComplexVector x, int offs, int n, int nsmall, PrintParameters pp) { + return formatComplexVector(x, offs, n, nsmall, pp.getDigits(), pp.getScipen(), pp.getNaWidth()); + } + + @TruffleBoundary + static ComplexVectorMetrics formatComplexVector(RAbstractComplexVector x, int offs, int n, int nsmall, int digits, int sciPen, int naWidth) { int wr; int dr; @@ -128,7 +135,7 @@ final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVector> { } else { /* real part */ - tmp = zprecr(xi, pp.getDigits()); + tmp = zprecr(xi, digits); if (!RRuntime.isFinite(tmp.getRealPart())) { if (RRuntime.isNAorNaN(tmp.getRealPart())) { @@ -142,7 +149,7 @@ final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVector> { if (xi.getRealPart() != 0) { allReZero = false; } - ScientificDouble sd = DoubleVectorPrinter.scientific(tmp.getRealPart(), pp); + ScientificDouble sd = DoubleVectorPrinter.scientific(tmp.getRealPart(), digits); left = sd.kpower + 1; if (sd.roundingwidens) { @@ -186,7 +193,7 @@ final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVector> { if (xi.getImaginaryPart() != 0) { allImZero = false; } - ScientificDouble sd = DoubleVectorPrinter.scientific(tmp.getImaginaryPart(), pp); + ScientificDouble sd = DoubleVectorPrinter.scientific(tmp.getImaginaryPart(), digits); left = sd.kpower + 1; if (sd.roundingwidens) { @@ -220,7 +227,7 @@ final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVector> { /* overall format for real part */ - if (pp.getDigits() == 0) { + if (digits == 0) { rt = 0; } if (mxl != RRuntime.INT_MIN_VALUE) { @@ -244,7 +251,7 @@ final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVector> { /* overall format for imaginary part */ - if (pp.getDigits() == 0) { + if (digits == 0) { irt = 0; } if (imxl != RRuntime.INT_MIN_VALUE) { @@ -270,7 +277,7 @@ final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVector> { if (allReZero) { er = dr = 0; wr = wF; - if (iwF <= wi + pp.getScipen()) { + if (iwF <= wi + sciPen) { ei = 0; if (nsmall > irt) { irt = nsmall; @@ -280,7 +287,7 @@ final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVector> { wi = iwF; } } else if (allImZero) { - if (wF <= wr + pp.getScipen()) { + if (wF <= wr + sciPen) { er = 0; if (nsmall > rt) { rt = nsmall; @@ -291,7 +298,7 @@ final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVector> { } ei = di = 0; wi = iwF; - } else if (wF + iwF < wr + wi + 2 * pp.getScipen()) { + } else if (wF + iwF < wr + wi + 2 * sciPen) { er = 0; if (nsmall > rt) { rt = nsmall; @@ -334,8 +341,8 @@ final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVector> { /* finally, ensure that there is space for NA */ - if (naflag && wr + wi + 2 < pp.getNaWidth()) { - wr += (pp.getNaWidth() - (wr + wi + 2)); + if (naflag && wr + wi + 2 < naWidth) { + wr += (naWidth - (wr + wi + 2)); } return new ComplexVectorMetrics(wr, dr, er, wi, di, ei); @@ -343,15 +350,72 @@ final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVector> { private static RoundArithmetic round = new Round.RoundArithmetic(); + private static final int MAX_DIGITS = 22; + private static RComplex zprecr(RComplex x, int digits) { - return round.opd(x.getRealPart(), x.getImaginaryPart(), digits); + double m1 = Math.abs(x.getRealPart()); + double m2 = Math.abs(x.getImaginaryPart()); + double m = 0; + if (Double.isFinite(m1)) { + m = m1; + } + if (Double.isFinite(m2) && m2 > m) { + m = m2; + } + if (m == 0.0) { + return x; + } + if (!Double.isFinite(digits)) { + if (digits > 0) { + return x; + } else { + return RComplex.valueOf(0, 0); + } + } + int dig = (int) Math.floor(digits + 0.5); + if (dig > MAX_DIGITS) { + return x; + } else if (dig < 1) { + dig = 1; + } + int mag = (int) Math.floor(Math.log10(m)); + dig = dig - mag - 1; + if (dig > 306) { + double pow10 = 1.0e4; + RComplex tmp = round.opd(pow10 * x.getRealPart(), pow10 * x.getImaginaryPart(), dig - 4); + return RComplex.valueOf(tmp.getRealPart() / pow10, tmp.getImaginaryPart() / pow10); + } else { + return round.opd(x.getRealPart(), x.getImaginaryPart(), dig); + } + } + + @TruffleBoundary + public static String encodeComplex(RComplex x) { + return encodeComplex(x, 15, 0, RRuntime.STRING_NA); + } + + @TruffleBoundary + public static String encodeComplex(RComplex x, int digits) { + return encodeComplex(x, digits, 0, RRuntime.STRING_NA); + } + + @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); } + @TruffleBoundary static String encodeComplex(RComplex x, ComplexVectorMetrics cvm, PrintParameters pp) { + return encodeComplex(x, cvm, pp.getDigits(), pp.getNaString()); + } + + @TruffleBoundary + static String encodeComplex(RComplex x, ComplexVectorMetrics cvm, int digits, String naString) { if (RRuntime.isNA(x.getRealPart()) || RRuntime.isNA(x.getImaginaryPart())) { - return DoubleVectorPrinter.encodeReal(RRuntime.DOUBLE_NA, cvm.maxWidth, 0, 0, '.', pp); + return DoubleVectorPrinter.encodeReal(RRuntime.DOUBLE_NA, cvm.maxWidth, 0, 0, '.', naString); } else { - String s = encodeComplex(x, cvm.wr, cvm.dr, cvm.er, cvm.wi, cvm.di, cvm.ei, '.', pp); + String s = encodeComplex(x, cvm.wr, cvm.dr, cvm.er, cvm.wi, cvm.di, cvm.ei, '.', digits, naString); int g = cvm.maxWidth - cvm.wr - cvm.wi - 2; if (g > 0) { // fill the remaining space by blanks to fit the maxWidth @@ -362,7 +426,8 @@ final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVector> { } } - private static String encodeComplex(RComplex x, int wr, int dr, int er, int wi, int di, int ei, char cdec, PrintParameters pp) { + @TruffleBoundary + private static String encodeComplex(RComplex x, int wr, int dr, int er, int wi, int di, int ei, char cdec, int digits, String naString) { String buff; String im; String re; @@ -385,27 +450,27 @@ final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVector> { String fmt = "%" + Utils.asBlankArg(g) + "s"; buff = Utils.snprintf(NB, fmt, /* was "%*s%*s", R_print.gap, "", */ - pp.getNaString()); + naString); } else { /* * formatComplex rounded, but this does not, and we need to keep it that way so we don't * get strange trailing zeros. But we do want to avoid printing small exponentials that * are probably garbage. */ - y = zprecr(x, pp.getDigits()); + y = zprecr(x, digits); if (y.getRealPart() == 0.) { - re = DoubleVectorPrinter.encodeReal(y.getRealPart(), wr, dr, er, cdec, pp); + re = DoubleVectorPrinter.encodeReal(y.getRealPart(), wr, dr, er, cdec, naString); } else { - re = DoubleVectorPrinter.encodeReal(xr, wr, dr, er, cdec, pp); + re = DoubleVectorPrinter.encodeReal(xr, wr, dr, er, cdec, naString); } flagNegIm = xi < 0; if (flagNegIm) { xi = -xi; } if (y.getImaginaryPart() == 0.) { - im = DoubleVectorPrinter.encodeReal(y.getImaginaryPart(), wi, di, ei, cdec, pp); + im = DoubleVectorPrinter.encodeReal(y.getImaginaryPart(), wi, di, ei, cdec, naString); } else { - im = DoubleVectorPrinter.encodeReal(xi, wi, di, ei, cdec, pp); + im = DoubleVectorPrinter.encodeReal(xi, wi, di, ei, cdec, naString); } buff = snprintf(NB, "%s%s%si", re, flagNegIm ? "-" : "+", im); } 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 457b1c404ba589315ba895b2bb3173381b463041..3bec697593cce250ab55be0995abc261d476d914 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 @@ -17,12 +17,14 @@ import java.io.IOException; import java.math.RoundingMode; import java.text.DecimalFormat; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; //Transcribed from GnuR, src/main/format.c -final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { +public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { static final DoubleVectorPrinter INSTANCE = new DoubleVectorPrinter(); @@ -69,7 +71,13 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { } } + @TruffleBoundary static DoubleVectorMetrics formatDoubleVector(RAbstractDoubleVector x, int offs, int n, int nsmall, PrintParameters pp) { + return formatDoubleVector(x, offs, n, nsmall, pp.getDigits(), pp.getScipen(), pp.getNaWidth()); + } + + @TruffleBoundary + static DoubleVectorMetrics formatDoubleVector(RAbstractDoubleVector x, int offs, int n, int nsmall, int digits, int sciPen, int naWidth) { int left; int right; int sleft; @@ -115,7 +123,7 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { neginf = true; } } else { - ScientificDouble sd = scientific(xi, pp); + ScientificDouble sd = scientific(xi, digits); sgn = sd.sgn; nsig = sd.nsig; kpower = sd.kpower; @@ -157,16 +165,16 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { /* * F Format: use "F" format WHENEVER we use not more space than 'E' and still satisfy * 'R_print.digits' {but as if nsmall==0 !} - * + * * E Format has the form [S]X[.XXX]E+XX[X] - * + * * This is indicated by setting *e to non-zero (usually 1) If the additional exponent digit * is required *e is set to 2 */ /*-- These 'mxsl' & 'rgt' are used in F Format * AND in the ____ if(.) "F" else "E" ___ below: */ - if (pp.getDigits() == 0) { + if (digits == 0) { rgt = 0; } if (mxl < 0) { @@ -184,7 +192,7 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { if (mxns != RRuntime.INT_MIN_VALUE) { d = mxns - 1; w = neg + (d != 0 ? 1 : 1) + d + 4 + e; /* width for E format */ - if (wF <= w + pp.getScipen()) { /* Fixpoint if it needs less space */ + if (wF <= w + sciPen) { /* Fixpoint if it needs less space */ e = 0; if (nsmall > rgt) { rgt = nsmall; @@ -198,8 +206,8 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { d = 0; e = 0; } - if (naflag && w < pp.getNaWidth()) { - w = pp.getNaWidth(); + if (naflag && w < naWidth) { + w = naWidth; } if (nanflag && w < 3) { w = 3; @@ -242,12 +250,18 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { } } + @TruffleBoundary public static ScientificDouble scientific(double x, PrintParameters pp) { + return scientific(x, pp.getDigits()); + } + + @TruffleBoundary + public static ScientificDouble scientific(double x, int digits) { /* * for a number x , determine sgn = 1_{x < 0} {0/1} kpower = Exponent of 10; nsig = * min(R_print.digits, #{significant digits of alpha}) roundingwidens = 1 if rounding causes * x to increase in width, 0 otherwise - * + * * where |x| = alpha * 10^kpower and 1 <= alpha < 10 */ double alpha; @@ -276,7 +290,7 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { r = x; } - if (pp.getDigits() >= DBL_DIG + 1) { + if (digits >= DBL_DIG + 1) { // TODO: // format_via_sprintf(r, pp.getDigits(), kpower, nsig); roundingwidens = false; @@ -284,8 +298,8 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { throw new UnsupportedOperationException(); } - kp = (int) Math.floor(Math.log10(r)) - pp.getDigits() + 1; // r = |x|; - // 10^(kp + digits - 1) <= r + kp = (int) Math.floor(Math.log10(r)) - digits + 1; // r = |x|; + // 10^(kp + digits - 1) <= r double rPrec = r; /* use exact scaling factor in double precision, if possible */ @@ -306,7 +320,7 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { } else { rPrec /= Math.pow(10, kp); } - if (rPrec < tbl[pp.getDigits()]) { + if (rPrec < tbl[digits]) { rPrec *= 10.0; kp--; } @@ -316,8 +330,8 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { */ alpha = Math.round(rPrec); - nsig = pp.getDigits(); - for (j = 1; j <= pp.getDigits(); j++) { + nsig = digits; + for (j = 1; j <= digits; j++) { alpha /= 10.0; if (alpha == Math.floor(alpha)) { nsig--; @@ -325,11 +339,11 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { break; } } - if (nsig == 0 && pp.getDigits() > 0) { + if (nsig == 0 && digits > 0) { nsig = 1; kp += 1; } - kpower = kp + pp.getDigits() - 1; + kpower = kp + digits - 1; /* * Scientific format may do more rounding than fixed format, e.g. 9996 with 3 digits is @@ -338,7 +352,7 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { * decimal place that will be cut off by rounding */ - int rgt = pp.getDigits() - kpower; + int rgt = digits - kpower; /* bound rgt by 0 and KP_MAX */ rgt = rgt < 0 ? 0 : rgt > KP_MAX ? KP_MAX : rgt; double fuzz = 0.5 / tbl[1 + rgt]; @@ -350,11 +364,34 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { return new ScientificDouble(sgn, kpower, nsig, roundingwidens); } + @TruffleBoundary + public static String encodeReal(double x) { + return encodeReal(x, 15, '.', 0, RRuntime.STRING_NA); + } + + @TruffleBoundary + public static String encodeReal(double x, int digits) { + return encodeReal(x, digits, '.', 0, RRuntime.STRING_NA); + } + + @TruffleBoundary + public static String encodeReal(double x, int digits, char cdec, int sciPen, String naString) { + DoubleVectorMetrics dm = formatDoubleVector(RDataFactory.createDoubleVectorFromScalar(x), 0, 1, 0, digits, sciPen, naString.length()); + return encodeReal(x, dm.maxWidth, dm.d, dm.e, cdec, naString); + } + + @TruffleBoundary + static String encodeReal(double initialX, int w, int d, int e, char cdec, PrintParameters pp) { + return encodeReal(initialX, w, d, e, cdec, pp.getNaString()); + } + + @TruffleBoundary static String encodeReal(double x, DoubleVectorMetrics dm, PrintParameters pp) { return encodeReal(x, dm.maxWidth, dm.d, dm.e, '.', pp); } - static String encodeReal(double initialX, int w, int d, int e, char cdec, PrintParameters pp) { + @TruffleBoundary + static String encodeReal(double initialX, int w, int d, int e, char cdec, String naString) { final String buff; String fmt; @@ -365,7 +402,7 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { int numBlanks = Math.min(w, (NB - 1)); String naFmt = "%" + Utils.asBlankArg(numBlanks) + "s"; if (RRuntime.isNA(x)) { - buff = snprintf(NB, naFmt, pp.getNaString()); + buff = snprintf(NB, naFmt, naString); } else if (RRuntime.isNAorNaN(x)) { buff = snprintf(NB, naFmt, "NaN"); } else if (x > 0) { @@ -382,8 +419,7 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> { buff = snprintf(NB, fmt, x); } } else { /* e = 0 */ - StringBuilder sb = new StringBuilder("#.#"); - DecimalFormat df = new DecimalFormat(sb.toString()); + DecimalFormat df = new DecimalFormat("#.#"); df.setRoundingMode(RoundingMode.HALF_EVEN); df.setDecimalSeparatorAlwaysShown(false); df.setMinimumFractionDigits(d); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/EnvironmentPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/EnvironmentPrinter.java index e9755ccb1abd8632640d7b3d9adf07c67c842c34..3060c0f03d7634be0f0426e175e42901cdbf6e7d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/EnvironmentPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/EnvironmentPrinter.java @@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.builtin.base.printer; import java.io.IOException; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.env.REnvironment; final class EnvironmentPrinter extends AbstractValuePrinter<REnvironment> { @@ -35,6 +36,7 @@ final class EnvironmentPrinter extends AbstractValuePrinter<REnvironment> { } @Override + @TruffleBoundary protected void printValue(REnvironment value, PrintContext printCtx) throws IOException { printCtx.output().print(value.getPrintName()); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExpressionPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExpressionPrinter.java index 4e55b86b5d370abb41758e782e01cf11ce7e7bb7..d8fcdd5d2926f7fbae17bbc8913cc2097940d3e5 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExpressionPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExpressionPrinter.java @@ -25,10 +25,10 @@ package com.oracle.truffle.r.nodes.builtin.base.printer; import java.io.IOException; import java.io.PrintWriter; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RExpression; -import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RStringVector; final class ExpressionPrinter extends AbstractValuePrinter<RExpression> { @@ -42,15 +42,15 @@ final class ExpressionPrinter extends AbstractValuePrinter<RExpression> { private static RAttributeProfiles dummyAttrProfiles = RAttributeProfiles.create(); @Override + @TruffleBoundary protected void printValue(RExpression expr, PrintContext printCtx) throws IOException { final PrintWriter out = printCtx.output(); final PrintContext valPrintCtx = printCtx.cloneContext(); valPrintCtx.parameters().setSuppressIndexLabels(true); out.print("expression("); - RList exprs = expr.getList(); RStringVector names = (RStringVector) expr.getAttr(dummyAttrProfiles, RRuntime.NAMES_ATTR_KEY); - for (int i = 0; i < exprs.getLength(); i++) { + for (int i = 0; i < expr.getLength(); i++) { if (i != 0) { out.print(", "); } @@ -58,7 +58,7 @@ final class ExpressionPrinter extends AbstractValuePrinter<RExpression> { out.print(names.getDataAt(i)); out.print(" = "); } - ValuePrinters.INSTANCE.print(exprs.getDataAt(i), valPrintCtx); + ValuePrinters.INSTANCE.print(expr.getDataAt(i), valPrintCtx); } out.print(')'); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExternalPtrPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExternalPtrPrinter.java index 82a4eac59498b326b52a4df376359b84d82293b8..46e85c82dfb38a171198a2a01ba7e87a09fd8325 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExternalPtrPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExternalPtrPrinter.java @@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.builtin.base.printer; import java.io.IOException; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.data.RExternalPtr; final class ExternalPtrPrinter extends AbstractValuePrinter<RExternalPtr> { @@ -35,6 +36,7 @@ final class ExternalPtrPrinter extends AbstractValuePrinter<RExternalPtr> { } @Override + @TruffleBoundary protected void printValue(RExternalPtr value, PrintContext printCtx) throws IOException { printCtx.output().print(""); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FactorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FactorPrinter.java index 220a795ec56c3b4b0a9feb88f150c7ddbc386d62..9cbb2a9c13abdb8102a4f3d5ffb622989a457e23 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FactorPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FactorPrinter.java @@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base.printer; import java.io.IOException; import java.io.PrintWriter; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RFactor; import com.oracle.truffle.r.runtime.data.RVector; @@ -43,11 +44,12 @@ final class FactorPrinter extends AbstractValuePrinter<RAbstractIntVector> { @SuppressWarnings("unused") private static RAttributeProfiles dummyAttrProfiles = RAttributeProfiles.create(); @Override + @TruffleBoundary protected void printValue(RAbstractIntVector operand, PrintContext printCtx) throws IOException { // TODO: this should be handled by an S3 function. Should it? For example, in C code for // split, there is direct call to getAttrib. This should be refactored to use // AttributeAccess node or even Factor.GetLevels node. The same holds for the access - RVector levels = RFactor.getLevels(operand); + RVector<?> levels = RFactor.getLevels(operand); String[] strings; if (levels == null) { strings = new String[0]; @@ -61,7 +63,8 @@ final class FactorPrinter extends AbstractValuePrinter<RAbstractIntVector> { RAbstractVector v = RClosures.createFactorToVector(operand, true, levels); PrintContext vectorPrintCtx = printCtx.cloneContext(); vectorPrintCtx.parameters().setQuote(false); - ValuePrinters.INSTANCE.println(v, vectorPrintCtx); + ValuePrinters.INSTANCE.print(v, vectorPrintCtx); + ValuePrinters.printNewLine(printCtx); final PrintWriter out = printCtx.output(); out.print("Levels:"); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FunctionPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FunctionPrinter.java index 0123f7ed4a1678aa21448eed250b79dea1329c99..15be08089ae5981033eebd892c300a56eb68abe4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FunctionPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FunctionPrinter.java @@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base.printer; import java.io.IOException; import java.io.PrintWriter; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.nodes.RRootNode; import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.function.FormalArguments; @@ -45,6 +46,7 @@ final class FunctionPrinter extends AbstractValuePrinter<RFunction> { } @Override + @TruffleBoundary protected void printValue(RFunction operand, PrintContext printCtx) throws IOException { final PrintWriter out = printCtx.output(); final PrintContext valPrintCtx = printCtx.cloneContext(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java index f47b7a21b9c30be4a24e3649121602495157e221..473cbbd1c94829812aa19fdb46f9f2d10627f36e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java @@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.builtin.base.printer; import java.io.IOException; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.data.RLanguage; @@ -36,6 +37,7 @@ final class LanguagePrinter extends AbstractValuePrinter<RLanguage> { } @Override + @TruffleBoundary protected void printValue(RLanguage language, PrintContext printCtx) throws IOException { printCtx.output().print(RDeparse.deparse(language, RDeparse.DEFAULT_Cutoff, false, 0, -1)); } 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 0d1eb278615243b701702dc3c2a2d963d5e4332f..debd2e46ff396ff3d567e6f2d90fd1a13ee32bc6 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 @@ -17,6 +17,7 @@ import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.snprintf; import java.io.IOException; import java.io.PrintWriter; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.runtime.RDeparse; @@ -51,6 +52,7 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> { private static int TAGBUFLEN = 256; @Override + @TruffleBoundary protected void printValue(RAbstractListVector s, PrintContext printCtx) throws IOException { RAbstractIntVector dims = Utils.<RAbstractIntVector> castTo( s.getAttr(dummyAttrProfiles, RRuntime.DIM_ATTR_KEY)); @@ -84,7 +86,7 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> { } } else if (tmp instanceof RAbstractIntVector) { RAbstractIntVector iv = (RAbstractIntVector) tmp; - if (printCtx.printerNode().inherits(iv, "factor", RRuntime.LOGICAL_FALSE)) { + if (printCtx.printerNode().inherits(iv, RRuntime.CLASS_FACTOR)) { /* factors are stored as integers */ pbuf = snprintf(115, "factor,%d", iv.getLength()); } else { @@ -155,6 +157,7 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> { StringVectorPrinter.INSTANCE.print(tt, cc); } + @TruffleBoundary static void printNoDimList(RAbstractContainer s, PrintContext printCtx) throws IOException { final PrintParameters pp = printCtx.parameters(); final PrintWriter out = printCtx.output(); @@ -211,7 +214,8 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> { out.println(tagbuf); Object si = s.getDataAtAsObject(i); - ValuePrinters.INSTANCE.println(si, printCtx); + ValuePrinters.INSTANCE.print(si, printCtx); + ValuePrinters.printNewLine(printCtx); tagbuf.setLength(taglen); // reset tag buffer to the original value } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/NullPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/NullPrinter.java index 06094e6e6def7b1548151edde328fc8439299d5c..2e64fe897ee1334b135e94e359e7cb6d07f7892a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/NullPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/NullPrinter.java @@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.builtin.base.printer; import java.io.IOException; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RNull; @@ -36,6 +37,7 @@ final class NullPrinter extends AbstractValuePrinter<RNull> { } @Override + @TruffleBoundary protected void printValue(RNull value, PrintContext printCtx) throws IOException { printCtx.output().print(RRuntime.NULL); } 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 3eceacda2ba0b76ab4e83edca50b65dd2998c199..9dabad114d57463555f70c483b5dbc381a9abc9b 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 @@ -15,6 +15,7 @@ import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.snprintf; import java.io.IOException; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -44,6 +45,7 @@ final class PairListPrinter extends AbstractValuePrinter<RPairList> { private static RAttributeProfiles dummyAttrProfiles = RAttributeProfiles.create(); @Override + @TruffleBoundary protected void printValue(RPairList s, PrintContext printCtx) throws IOException { final RAbstractIntVector dims = Utils.<RAbstractIntVector> castTo( s.getAttr(dummyAttrProfiles, RRuntime.DIM_ATTR_KEY)); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintContext.java index 7b4eb5c7727a5589de0b44c2382bc001f5f37f7e..4d89ced83a41057ff75fa84122fe6e841dcb9fae 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintContext.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintContext.java @@ -26,6 +26,7 @@ import java.util.ArrayDeque; import java.util.HashMap; import java.util.Map; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RInternalError; final class PrintContext { @@ -97,6 +98,7 @@ final class PrintContext { return cloned; } + @TruffleBoundary static PrintContext enter(ValuePrinterNode printerNode, PrintParameters parameters, WriterFactory wf) { ArrayDeque<PrintContext> ctxStack = printCtxTL.get(); if (ctxStack == null) { @@ -114,6 +116,7 @@ final class PrintContext { } } + @TruffleBoundary static PrintContext leave() { ArrayDeque<PrintContext> ctxStack = printCtxTL.get(); 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 bcd3fdf41db6622e1bed3c2aada118854360e1a6..27deabed40d5cdf104b616f879fe99d9f7348c85 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 @@ -13,6 +13,7 @@ package com.oracle.truffle.r.nodes.builtin.base.printer; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; //Transcribed from GnuR, src/include/Print.h @@ -56,6 +57,7 @@ public final class PrintParameters { // default constructor } + @TruffleBoundary PrintParameters(Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, @SuppressWarnings("unused") boolean noOpt) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RawVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RawVectorPrinter.java index e0c7e8d97213fc5d6445020d9f11bafc1c4909d0..32b5670b9af97b5a6749da0941b04c6801690d13 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RawVectorPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RawVectorPrinter.java @@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.builtin.base.printer; import java.io.IOException; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; final class RawVectorPrinter extends VectorPrinter<RAbstractRawVector> { @@ -56,6 +57,7 @@ final class RawVectorPrinter extends VectorPrinter<RAbstractRawVector> { } @Override + @TruffleBoundary protected void printElement(int i, FormatMetrics fm) throws IOException { String rs = vector.getDataAt(i).toString(); int gap = fm.maxWidth - 2; @@ -70,6 +72,7 @@ final class RawVectorPrinter extends VectorPrinter<RAbstractRawVector> { } @Override + @TruffleBoundary protected void printEmptyVector() throws IOException { printCtx.output().print("raw(0)"); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/SymbolPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/SymbolPrinter.java index 7f8080ae07cdef0ea3823da04085b9754f96c8cd..19451dfcbf5e7dc936254d14ef4d57b7af44566e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/SymbolPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/SymbolPrinter.java @@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.builtin.base.printer; import java.io.IOException; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.data.RSymbol; @@ -36,6 +37,7 @@ final class SymbolPrinter extends AbstractValuePrinter<RSymbol> { } @Override + @TruffleBoundary protected void printValue(RSymbol value, PrintContext printCtx) throws IOException { printCtx.output().print(RDeparse.deparse(value, RDeparse.DEFAULT_Cutoff, true, RDeparse.SIMPLEDEPARSE, -1)); } diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/CastStringNodeGenSampler.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/TruffleObjectPrinter.java similarity index 63% rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/CastStringNodeGenSampler.java rename to com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/TruffleObjectPrinter.java index 777b8e0e05be525d5a074cf03e726f00ac77707a..446fb67a2aeae19e436f25a977926dc15b4c36f4 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/CastStringNodeGenSampler.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/TruffleObjectPrinter.java @@ -20,25 +20,24 @@ * 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.nodes.builtin.base.printer; -import com.oracle.truffle.r.nodes.casts.CastNodeSampler; -import com.oracle.truffle.r.nodes.casts.TypeExpr; -import com.oracle.truffle.r.runtime.data.RNull; +import java.io.IOException; -public class CastStringNodeGenSampler extends CastNodeSampler<CastStringNodeGen> { +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.interop.TruffleObject; - public CastStringNodeGenSampler(CastStringNodeGen castNode) { - super(castNode); +final class TruffleObjectPrinter extends AbstractValuePrinter<TruffleObject> { + + static TruffleObjectPrinter INSTANCE = new TruffleObjectPrinter(); + + private TruffleObjectPrinter() { + // singleton } @Override - public TypeExpr resultTypes(TypeExpr inputType) { - TypeExpr rt = super.resultTypes(inputType); - if (castNode.convertEmptyVectorToNull()) { - return rt.or(TypeExpr.union(RNull.class)); - } else { - return rt; - } + @TruffleBoundary + protected void printValue(TruffleObject value, PrintContext printCtx) throws IOException { + printCtx.output().print("[external object]"); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinter.java index f9d1d0ec091dca10a4bdb2e772b192247c59de9f..111102cbe3d3d33c7701955cbf29158c84d0f391 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinter.java @@ -35,14 +35,4 @@ interface ValuePrinter<T> { void print(T value, PrintContext printCtx) throws IOException; - default void println(T value, PrintContext printCtx) throws IOException { - print(value, printCtx); - // - if (!Boolean.TRUE.equals(printCtx.getAttribute(DONT_PRINT_NL_ATTR))) { - printCtx.output().println(); - } else { - // Clear the instruction attribute - printCtx.setAttribute(DONT_PRINT_NL_ATTR, false); - } - } } 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 d124cf1fcf353ea953fba02552e7f63f02f3d5d2..3310513ca6ea51d98ca80c8224cbd52287e97a76 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 @@ -24,15 +24,21 @@ package com.oracle.truffle.r.nodes.builtin.base.printer; import java.io.IOException; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; -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.TruffleObject; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode; -import com.oracle.truffle.r.nodes.builtin.base.Inherits; -import com.oracle.truffle.r.nodes.builtin.base.InheritsNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.InheritsBuiltin; +import com.oracle.truffle.r.nodes.builtin.base.InheritsBuiltinNodeGen; import com.oracle.truffle.r.nodes.builtin.base.IsMethodsDispatchOn; import com.oracle.truffle.r.nodes.builtin.base.IsMethodsDispatchOnNodeGen; import com.oracle.truffle.r.nodes.builtin.base.IsS4; @@ -45,20 +51,323 @@ import com.oracle.truffle.r.nodes.builtin.base.IsTypeFunctionsFactory.IsListNode import com.oracle.truffle.r.nodes.builtin.base.IsTypeFunctionsFactory.IsObjectNodeGen; import com.oracle.truffle.r.nodes.unary.CastStringNode; 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.data.RAttributeProfiles; +import com.oracle.truffle.r.runtime.data.RAttributeStorage; +import com.oracle.truffle.r.runtime.data.RAttributes; +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.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; +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; import com.oracle.truffle.r.runtime.nodes.RBaseNode; -public abstract class ValuePrinterNode extends RBaseNode { +public final class ValuePrinterNode extends RBaseNode { @Child private IsArray isArrayBuiltIn = IsArrayNodeGen.create(null); @Child private IsList isListBuiltIn = IsListNodeGen.create(null); - @Child private Inherits inheritsBuiltIn = InheritsNodeGen.create(null); + @Child private InheritsBuiltin inheritsBuiltinBuiltIn = InheritsBuiltinNodeGen.create(null); @Child private IsS4 isS4BuiltIn = IsS4NodeGen.create(null); @Child private IsObject isObjectBuiltIn = IsObjectNodeGen.create(null); @Child private IsMethodsDispatchOn isMethodDispatchOnBuiltIn = IsMethodsDispatchOnNodeGen.create(null); @Child private CastStringNode castStringNode = CastStringNode.createNonPreserving(); @Child private BoxPrimitiveNode boxPrimitiveNode = BoxPrimitiveNode.create(); + @Child private ConvertTruffleObjectNode convertTruffleObject; + + /** + * This node inspects non-R {@link TruffleObject}s and tries to create wrappers for them that + * mimic R data structures. + */ + public static final class ConvertTruffleObjectNode extends Node { + + @Child private Node hasSizeNode = com.oracle.truffle.api.interop.Message.HAS_SIZE.createNode(); + @Child private Node getSizeNode = com.oracle.truffle.api.interop.Message.GET_SIZE.createNode(); + @Child private Node readNode = com.oracle.truffle.api.interop.Message.READ.createNode(); + @Child private Node isBoxedNode = com.oracle.truffle.api.interop.Message.IS_BOXED.createNode(); + @Child private Node unboxNode = com.oracle.truffle.api.interop.Message.UNBOX.createNode(); + @Child private Node keysNode = com.oracle.truffle.api.interop.Message.KEYS.createNode(); + + public Object convert(VirtualFrame frame, TruffleObject obj) { + class RStringWrapper extends TruffleObjectWrapper implements RAbstractStringVector { + final TruffleObject object; + + RStringWrapper(int length, TruffleObject object) { + super(length); + this.object = object; + } + + @Override + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } + + @Override + public String getDataAt(int index) { + Object value; + try { + value = ForeignAccess.sendRead(readNode, frame, object, index); + if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, frame, (TruffleObject) value)) { + value = ForeignAccess.sendUnbox(unboxNode, frame, (TruffleObject) value); + } + } catch (UnknownIdentifierException | UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + return (String) value; + } + + @Override + public RStringVector getImplicitClass() { + return RStringVector.implicitClassHeader; + } + + @Override + public RStringVector materialize() { + throw RInternalError.shouldNotReachHere(); + } + } + try { + if (ForeignAccess.sendHasSize(hasSizeNode, frame, obj)) { + CompilerDirectives.transferToInterpreter(); + int size = (Integer) ForeignAccess.sendGetSize(getSizeNode, frame, obj); + boolean allBoolean = true; + boolean allInteger = true; + boolean allNumber = true; + boolean allString = true; + for (int i = 0; i < size; i++) { + Object value = ForeignAccess.sendRead(readNode, frame, obj, i); + if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, frame, (TruffleObject) value)) { + value = ForeignAccess.sendUnbox(unboxNode, frame, (TruffleObject) value); + } + allBoolean &= value instanceof Boolean; + allInteger &= value instanceof Integer; + allNumber &= value instanceof Number; + allString &= value instanceof String; + } + if (allBoolean) { + class RLogicalWrapper extends TruffleObjectWrapper implements RAbstractLogicalVector { + + RLogicalWrapper(int length) { + super(length); + } + + @Override + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } + + @Override + public byte getDataAt(int index) { + Object value; + try { + value = ForeignAccess.sendRead(readNode, frame, obj, index); + if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, frame, (TruffleObject) value)) { + value = ForeignAccess.sendUnbox(unboxNode, frame, (TruffleObject) value); + } + } catch (UnknownIdentifierException | UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + return RRuntime.asLogical((Boolean) value); + } + + @Override + public RStringVector getImplicitClass() { + return RIntVector.implicitClassHeader; + } + + @Override + public RLogicalVector materialize() { + throw RInternalError.shouldNotReachHere(); + } + } + return new RLogicalWrapper(size); + } else if (allInteger) { + class RIntWrapper extends TruffleObjectWrapper implements RAbstractIntVector { + + RIntWrapper(int length) { + super(length); + } + + @Override + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } + + @Override + public int getDataAt(int index) { + Object value; + try { + value = ForeignAccess.sendRead(readNode, frame, obj, index); + if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, frame, (TruffleObject) value)) { + value = ForeignAccess.sendUnbox(unboxNode, frame, (TruffleObject) value); + } + } catch (UnknownIdentifierException | UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + return (Integer) value; + } + + @Override + public RStringVector getImplicitClass() { + return RIntVector.implicitClassHeader; + } + + @Override + public RIntVector materialize() { + throw RInternalError.shouldNotReachHere(); + } + } + return new RIntWrapper(size); + } else if (allNumber) { + class RDoubleWrapper extends TruffleObjectWrapper implements RAbstractDoubleVector { + + RDoubleWrapper(int length) { + super(length); + } + + @Override + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } + + @Override + public double getDataAt(int index) { + Object value; + try { + value = ForeignAccess.sendRead(readNode, frame, obj, index); + if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, frame, (TruffleObject) value)) { + value = ForeignAccess.sendUnbox(unboxNode, frame, (TruffleObject) value); + } + } catch (UnknownIdentifierException | UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + 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) { + return new RStringWrapper(size, obj); + } else { + class RListWrapper extends TruffleObjectWrapper implements RAbstractListVector { + + RListWrapper(int length) { + super(length); + } + + @Override + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } + + @Override + public Object getDataAt(int index) { + Object value; + try { + value = ForeignAccess.sendRead(readNode, frame, obj, index); + if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, frame, (TruffleObject) value)) { + value = ForeignAccess.sendUnbox(unboxNode, frame, (TruffleObject) value); + } + } catch (UnknownIdentifierException | UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + return value; + } + + @Override + public RStringVector getImplicitClass() { + return RList.implicitClassHeader; + } + + @Override + public RList materialize() { + throw RInternalError.shouldNotReachHere(); + } + } + return new RListWrapper(size); + } + } + TruffleObject keys = (TruffleObject) ForeignAccess.send(keysNode, frame, obj); + if (keys != null) { + int size = (Integer) ForeignAccess.sendGetSize(getSizeNode, frame, keys); + RAbstractStringVector abstractNames = new RStringWrapper(size, keys); + RStringVector names = RDataFactory.createStringVector(size); + for (int i = 0; i < size; i++) { + names.getDataWithoutCopying()[i] = abstractNames.getDataAt(i); + } + + class RListWrapper extends TruffleObjectWrapper implements RAbstractListVector { + + RListWrapper(int length) { + super(length); + initAttributes(RAttributes.createInitialized(new String[]{RRuntime.NAMES_ATTR_KEY, "is.truffle.object"}, new Object[]{names, RRuntime.LOGICAL_TRUE})); + } + + @Override + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } + + @Override + public Object getDataAt(int index) { + Object value; + try { + value = ForeignAccess.sendRead(readNode, frame, obj, names.getDataAt(index)); + if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, frame, (TruffleObject) value)) { + value = ForeignAccess.sendUnbox(unboxNode, frame, (TruffleObject) value); + } + } catch (UnknownIdentifierException | UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + return value; + } + + @Override + public RStringVector getImplicitClass() { + return RList.implicitClassHeader; + } + + @Override + public RStringVector getNames(RAttributeProfiles attrProfiles) { + return names; + } + + @Override + public RList materialize() { + throw RInternalError.shouldNotReachHere(); + } + } + return new RListWrapper(size); + } + } catch (InteropException e) { + // nothing to do + } + return obj; + } + } + public boolean isArray(Object o) { return RRuntime.fromLogical(isArrayBuiltIn.execute(o)); } @@ -67,8 +376,8 @@ public abstract class ValuePrinterNode extends RBaseNode { return RRuntime.fromLogical(isListBuiltIn.execute(o)); } - public boolean inherits(Object o, Object what, byte which) { - return RRuntime.fromLogical((Byte) inheritsBuiltIn.execute(o, what, which)); + public boolean inherits(Object o, Object what) { + return RRuntime.fromLogical((Byte) inheritsBuiltinBuiltIn.execute(o, what, false)); } public boolean isS4(Object o) { @@ -91,9 +400,187 @@ public abstract class ValuePrinterNode extends RBaseNode { return boxPrimitiveNode.execute(o); } - public abstract Object executeString(Object o, Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, boolean noOpt); + private Object convertTruffleObject(VirtualFrame frame, Object o) { + if (o instanceof TruffleObject && !(o instanceof RTypedValue)) { + if (convertTruffleObject == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + convertTruffleObject = insert(new ConvertTruffleObjectNode()); + } + return convertTruffleObject.convert(frame, (TruffleObject) o); + } + return o; + } + + public String execute(VirtualFrame frame, Object o, Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, boolean noOpt) { + try { + prettyPrint(convertTruffleObject(frame, o), new PrintParameters(digits, quote, naPrint, printGap, right, max, useSource, noOpt), RWriter::new); + return null; + } catch (IOException ex) { + throw RError.ioError(this, ex); + } + } + + private abstract static class TruffleObjectWrapper extends RAttributeStorage implements RAbstractVector { + + private final int length; + + TruffleObjectWrapper(int length) { + initAttributes(RAttributes.createInitialized(new String[]{"is.truffle.object"}, new Object[]{RRuntime.LOGICAL_TRUE})); + this.length = length; + } + + @Override + public RAbstractVector copy() { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public RVector<?> copyResized(int size, boolean fillNA) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public RAbstractVector copyWithNewDimensions(int[] newDimensions) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public RVector<?> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public RAbstractVector copyDropAttributes() { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public boolean isMatrix() { + return false; + } + + @Override + public boolean isArray() { + return false; + } + + @Override + public boolean checkCompleteness() { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public void setComplete(boolean complete) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public void setNA(Object store, int index) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public boolean isComplete() { + return false; + } + + @Override + public int getLength() { + return length; + } + + @Override + public RAbstractContainer resize(int size) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public boolean hasDimensions() { + return false; + } + + @Override + public int[] getDimensions() { + return null; + } + + @Override + public void setDimensions(int[] newDimensions) { + 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(RAttributeProfiles attrProfiles) { + return null; + } + + @Override + public void setNames(RStringVector newNames) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public RList getDimNames(RAttributeProfiles attrProfiles) { + return null; + } + + @Override + public void setDimNames(RList newDimNames) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public Object getRowNames(RAttributeProfiles attrProfiles) { + return null; + } + + @Override + public void setRowNames(RAbstractVector rowNames) { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public RStringVector getImplicitClass() { + return null; + } + + @Override + public RType getRType() { + return RType.Integer; + } + + @Override + public ForeignAccess getForeignAccess() { + throw RInternalError.shouldNotReachHere(); + } + } + + public Object prettyPrint(VirtualFrame frame, Object v, WriterFactory wf) { + return prettyPrint(convertTruffleObject(frame, v), wf); + } - public Object prettyPrint(Object v, WriterFactory wf) { + @TruffleBoundary + private Object prettyPrint(Object v, WriterFactory wf) { PrintParameters printParams = new PrintParameters(); printParams.setDefaults(); printParams.setSuppressIndexLabels(true); @@ -102,25 +589,13 @@ public abstract class ValuePrinterNode extends RBaseNode { ValuePrinters.INSTANCE.print(v, printCtx); return printCtx.output().getPrintReport(); } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); + throw RError.ioError(this, ex); } finally { PrintContext.leave(); } } - @Specialization - protected String prettyPrint(Object o, Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, boolean noOpt) { - try { - prettyPrint(o, new PrintParameters(digits, quote, naPrint, printGap, - right, max, useSource, noOpt), RWriter::new); - return null; - } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); - } - } - - private String prettyPrint(Object o, PrintParameters printParams, WriterFactory wf) - throws IOException { + private String prettyPrint(Object o, PrintParameters printParams, WriterFactory wf) throws IOException { PrintContext printCtx = PrintContext.enter(this, printParams, wf); try { prettyPrint(o, printCtx); @@ -132,17 +607,18 @@ public abstract class ValuePrinterNode extends RBaseNode { @TruffleBoundary private static void prettyPrint(Object o, PrintContext printCtx) throws IOException { - ValuePrinters.INSTANCE.println(o, printCtx); + ValuePrinters.INSTANCE.print(o, printCtx); + ValuePrinters.printNewLine(printCtx); } public static String prettyPrint(final Object value) { return (String) Truffle.getRuntime().createCallTarget(new RootNode(TruffleLanguage.class, null, null) { - @Child ValuePrinterNode valuePrinterNode = ValuePrinterNodeGen.create(); + @Child ValuePrinterNode valuePrinterNode = new ValuePrinterNode(); @Override public Object execute(VirtualFrame frame) { - return valuePrinterNode.prettyPrint(value, AnyVectorToStringVectorWriter::new); + return valuePrinterNode.prettyPrint(frame, value, AnyVectorToStringVectorWriter::new); } }).call(value); } 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 0a8481fdb54934d5c01687649cf8b879436a9791..aa6cd266a90167869b79d0974c54fd6fca3228ca 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 @@ -26,6 +26,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; +import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RAttributable; @@ -37,6 +38,7 @@ 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.RSymbol; +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; @@ -71,8 +73,17 @@ final class ValuePrinters implements ValuePrinter<Object> { if (v == RNull.instance) { NullPrinter.INSTANCE.print(null, printCtx); } else { - // Try to box a scalar primitive value to the respective vector - Object x = printCtx.printerNode().boxPrimitive(v); + // handle types that can appear via Truffle interop + Object x = v; + if (x instanceof Boolean) { + x = RRuntime.asLogical((Boolean) x); + } else if (x instanceof Long || x instanceof Short || x instanceof Float) { + x = ((Number) x).doubleValue(); + } else if (x instanceof Character) { + x = ((Character) x).toString(); + } + // try to box a scalar primitive value to the respective vector + x = printCtx.printerNode().boxPrimitive(x); ValuePrinter printer = printers.get(x.getClass()); if (printer == null) { if (x instanceof RAbstractIntVector && ((RAttributable) x).hasClass(RRuntime.CLASS_FACTOR)) { @@ -93,6 +104,9 @@ final class ValuePrinters implements ValuePrinter<Object> { printer = ListPrinter.INSTANCE; } else if (x instanceof REnvironment) { printer = EnvironmentPrinter.INSTANCE; + } else if (x instanceof TruffleObject) { + assert !(x instanceof RTypedValue); + printer = TruffleObjectPrinter.INSTANCE; } else { RInternalError.shouldNotReachHere("unexpected type: " + (x == null ? "null" : x.getClass())); } @@ -100,4 +114,13 @@ final class ValuePrinters implements ValuePrinter<Object> { printer.print(x, printCtx); } } + + public static void printNewLine(PrintContext printCtx) { + if (!Boolean.TRUE.equals(printCtx.getAttribute(DONT_PRINT_NL_ATTR))) { + printCtx.output().println(); + } else { + // Clear the instruction attribute + printCtx.setAttribute(DONT_PRINT_NL_ATTR, false); + } + } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..3df01c1c7d7d1a48ba36c5cff1156462a0c79fcb --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ContextSystemFunctionFactory.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016, 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.builtin.base.system; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.nodes.builtin.base.system.ContextSystemFunctionFactoryFactory.ContextRSystemFunctionNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.system.ContextSystemFunctionFactoryFactory.ContextRscriptSystemFunctionNodeGen; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRContext; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRContextFactory; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; + +/** + * A variant that uses {@code .fastr.context.r} for R sub-processes and throws an error otherwise. + * Used in systems that do not support {@code ProcessBuilder} and for R commands by + * {@link PreferContextSystemFunctionFactory}, for better performance. + */ +public class ContextSystemFunctionFactory extends SystemFunctionFactory { + private abstract static class ContextSystemFunctionNode extends RBaseNode { + public abstract Object execute(VirtualFrame frame, Object args, Object env, Object intern); + + } + + public abstract static class ContextRSystemFunctionNode extends ContextSystemFunctionNode { + @Child FastRContext.R contextRNode; + + private void initContextRNode() { + if (contextRNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + contextRNode = insert(FastRContextFactory.RNodeGen.create(null)); + } + + } + + @Specialization + protected Object systemFunction(VirtualFrame frame, RAbstractStringVector args, RAbstractStringVector env, boolean intern) { + initContextRNode(); + Object result = contextRNode.executeBuiltin(frame, args, env, intern); + return result; + } + } + + public abstract static class ContextRscriptSystemFunctionNode extends ContextSystemFunctionNode { + @Child FastRContext.Rscript contextRscriptNode; + + private void initContextRscriptNode() { + if (contextRscriptNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + contextRscriptNode = insert(FastRContextFactory.RscriptNodeGen.create(null)); + } + + } + + @Specialization + protected Object systemFunction(VirtualFrame frame, RAbstractStringVector args, RAbstractStringVector env, boolean intern) { + initContextRscriptNode(); + Object result = contextRscriptNode.executeBuiltin(frame, args, env, intern); + return result; + } + } + + @Override + public Object execute(VirtualFrame frame, String command, boolean intern) { + log(command, "Context"); + CommandInfo commandInfo = checkRCommand(command); + if (commandInfo != null) { + ContextSystemFunctionNode node = Utils.unShQuote(commandInfo.command).equals("R") ? ContextRSystemFunctionNodeGen.create() : ContextRscriptSystemFunctionNodeGen.create(); + Object result = node.execute(frame, RDataFactory.createStringVector(commandInfo.args, RDataFactory.COMPLETE_VECTOR), + RDataFactory.createStringVector(commandInfo.envDefs, RDataFactory.COMPLETE_VECTOR), intern); + return result; + } else { + throw cannotExecute(command); + } + } + + private static RError cannotExecute(String command) throws RError { + CompilerDirectives.transferToInterpreter(); + throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, command + " cannot be executed in a context"); + } + +} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/PreferContextSystemFunctionFactory.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/PreferContextSystemFunctionFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..14361ed25cef4cfcb5ed5837de0a2de9acd60bb9 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/PreferContextSystemFunctionFactory.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, 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. + */ +/** + * A variant that prefers to use {@code .fastr.context.r} for R sub-processes but backs off to + * {@code ProcessBuilder}. + */ +package com.oracle.truffle.r.nodes.builtin.base.system; + +import com.oracle.truffle.api.frame.VirtualFrame; + +public class PreferContextSystemFunctionFactory extends SystemFunctionFactory { + private ContextSystemFunctionFactory contextSystemFunctionFactory; + private ProcessSystemFunctionFactory processSystemFunctionFactory; + + @Override + public Object execute(VirtualFrame frame, String command, boolean intern) { + CommandInfo commandInfo = checkRCommand(command); + if (commandInfo == null) { + if (processSystemFunctionFactory == null) { + processSystemFunctionFactory = new ProcessSystemFunctionFactory(); + } + return processSystemFunctionFactory.execute(frame, command, intern); + } else { + if (contextSystemFunctionFactory == null) { + contextSystemFunctionFactory = new ContextSystemFunctionFactory(); + } + return contextSystemFunctionFactory.execute(frame, command, intern); + } + } +} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SystemFunction.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ProcessSystemFunctionFactory.java similarity index 72% rename from com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SystemFunction.java rename to com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ProcessSystemFunctionFactory.java index 0590d2becca1a0bc2cf94f3bafb57a962f85df7c..d1f8116fb1d97a82df6c308cdf8653f4c3576dc4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SystemFunction.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ProcessSystemFunctionFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -20,11 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.nodes.builtin.base; - -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.INTERNAL; +package com.oracle.truffle.r.nodes.builtin.base.system; import java.io.IOException; import java.io.InputStream; @@ -32,31 +28,26 @@ import java.lang.ProcessBuilder.Redirect; import java.util.Map; 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.api.frame.VirtualFrame; import com.oracle.truffle.r.runtime.ProcessOutputManager; -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.RStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -@RBuiltin(name = "system", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"command", "intern"}, behavior = COMPLEX) -public abstract class SystemFunction extends RBuiltinNode { - @Specialization +public class ProcessSystemFunctionFactory extends SystemFunctionFactory { + + @Override + public Object execute(VirtualFrame frame, String command, boolean intern) { + return execute(command, intern); + } + @TruffleBoundary - protected Object system(RAbstractStringVector command, byte internLogical) { + private Object execute(String command, boolean intern) { Object result; - boolean intern = RRuntime.fromLogical(internLogical); - String shell = RContext.getInstance().stateREnvVars.get("SHELL"); - if (shell == null) { - shell = "/bin/sh"; - } - if (RContext.getInstance().stateREnvVars.getMap().get("FASTR_LOGCHILD") != null) { - System.out.printf("FastR system: %s -c %s%n", shell, command.getDataAt(0)); - } - ProcessBuilder pb = new ProcessBuilder(shell, "-c", command.getDataAt(0)); + // GNU R uses popen which always invokes /bin/sh + String shell = "/bin/sh"; + log(String.format("%s -c \"%s\"", shell, command), "Process"); + ProcessBuilder pb = new ProcessBuilder(shell, "-c", command); updateEnvironment(pb); pb.redirectInput(Redirect.INHERIT); if (intern) { @@ -95,10 +86,16 @@ public abstract class SystemFunction extends RBuiltinNode { } catch (InterruptedException | IOException ex) { result = 127; } - RContext.getInstance().setVisible(false); return result; } + /** + * Any environment variables that have been added to this session must be forwarded to the + * process (Java does not provide a {@code setenv} call, so {@code Sys.setenv} calls only affect + * {@code stateEnvVars}. Any explicit settings in the command call (arising from the {@code env} + * argument to the {@code system2} call, will override these by virtue of being explicitly set + * in the new shell. + */ private static void updateEnvironment(ProcessBuilder pb) { Map<String, String> pEnv = pb.environment(); Map<String, String> rEnv = RContext.getInstance().stateREnvVars.getMap(); 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 new file mode 100644 index 0000000000000000000000000000000000000000..5ac50544b48058f5ec04a7f250edd6be0489e5d3 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java @@ -0,0 +1,56 @@ +/* + * 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.nodes.builtin.base.system; + +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.CUSTOM; +import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; +import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; + +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; +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 { + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); + + @Override + protected void createCasts(CastBuilder casts) { + 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()); + } + + @Specialization + protected Object system(VirtualFrame frame, String command, boolean intern) { + Object result = SystemFunctionFactory.getInstance().execute(frame, command.trim(), intern); + visibility.execute(frame, intern); + return result; + } + +} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunctionFactory.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunctionFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..424c395ed99bb0888971dc7cfa92e74c2333732c --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunctionFactory.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2016, 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.builtin.base.system; + +import java.io.IOException; +import java.nio.file.FileSystems; +import java.util.ArrayList; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.runtime.REnvVars; +import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.context.RContext; + +public abstract class SystemFunctionFactory { + private static String kind; + private static SystemFunctionFactory theInstance; + + static { + String className = System.getProperty("fastr.systemfunction.factory.class", "com.oracle.truffle.r.nodes.builtin.base.system.ProcessSystemFunctionFactory"); + try { + theInstance = (SystemFunctionFactory) Class.forName(className).newInstance(); + } catch (Exception ex) { + // CheckStyle: stop system..print check + Utils.rSuicide("Failed to instantiate class: " + className); + } + } + + @TruffleBoundary + public static SystemFunctionFactory getInstance() { + return theInstance; + } + + /** + * Implements the system {@code .Internal}. If {@code intern} is {@code true} the result is a + * character vector containing the output of the process, with a {@code status} attribute + * carrying the return code, else it is just the return code. + * + * {@code command} is a string with args separated by spaces with the first element enclosed in + * single quotes. + */ + public abstract Object execute(VirtualFrame frame, String command, boolean intern); + + @TruffleBoundary + protected void log(String command, String useKind) { + if (RContext.getInstance().stateREnvVars.getMap().get("FASTR_LOG_SYSTEM") != null) { + System.out.printf("FastR system (%s): %s%n", useKind, command); + } + + } + + @TruffleBoundary + protected void log(String command) { + log(command, kind); + } + + /** + * Encodes information collected by analyzing the command pass to {@code .Internal(system)}. + */ + public static final class CommandInfo { + public final String[] envDefs; + public final String command; + public final String[] args; + + public CommandInfo(String[] envDefs, String command, String[] args) { + this.envDefs = envDefs; + this.command = command; + this.args = args; + } + } + + /** + * Analyzes {@code command} to see if it is an R command that we can execute in a context. + * + * @return a {@link CommandInfo} object if the command can be executed in a context, else + * {@code null}. + */ + @TruffleBoundary + public static CommandInfo checkRCommand(String command) { + CommandInfo commandInfo = null; + String[] parts = command.split(" "); + /* The actual command may be prefixed by environment variable settings of the form X=Y */ + int i = 0; + while (parts[i].contains("=")) { + i++; + } + String rcommand = isFastR(parts[i]); + if (rcommand == null) { + return null; + } else { + String[] envDefs = new String[i]; + if (i != 0) { + System.arraycopy(parts, 0, envDefs, 0, i); + } + String[] args = new String[parts.length - i - 1]; + if (args.length > 0) { + System.arraycopy(parts, i + 1, args, 0, args.length); + } + commandInfo = new CommandInfo(envDefs, rcommand, args); + } + // check for and emulate selected R CMD cmd commands + if (commandInfo.args.length > 0) { + if (commandInfo.args[0].equals("CMD")) { + switch (commandInfo.args[1]) { + case "INSTALL": + // INSTALL pipes in "tools:::.install_packages()" + // We use "-e tools:::.install_packages()" as its simpler + ArrayList<String> newArgsList = new ArrayList<>(); + newArgsList.add("--no-restore"); + newArgsList.add("--slave"); + newArgsList.add("-e"); + newArgsList.add("tools:::.install_packages()"); + newArgsList.add("--args"); + StringBuffer sb = new StringBuffer(); + i = 2; + while (i < commandInfo.args.length) { + String arg = commandInfo.args[i]; + if (arg.equals("<") || arg.contains(">")) { + break; + } + sb.append("nextArg"); + sb.append(arg); + i++; + } + if (sb.length() > 0) { + newArgsList.add(sb.toString()); + } + while (i < commandInfo.args.length) { + newArgsList.add(commandInfo.args[i]); + i++; + } + String[] newArgs = new String[newArgsList.size()]; + newArgsList.toArray(newArgs); + commandInfo = new CommandInfo(commandInfo.envDefs, commandInfo.command, newArgs); + break; + + default: + commandInfo = null; + + } + } + } + return commandInfo; + } + + /** + * Returns {@code true} iff, {@code command} is {@code R} or {@code Rscript}. + */ + private static String isFastR(String command) { + // strip off quotes + String xc = Utils.unShQuote(command); + if (xc.equals("R") || xc.equals("Rscript")) { + return xc; + } + // often it is an absolute path + String rhome = REnvVars.rHome(); + if (isFullPath(rhome, "Rscript", xc)) { + return "Rscript"; + } + if (isFullPath(rhome, "R", xc)) { + return "R"; + } + return null; + } + + private static boolean isFullPath(String rhome, String rcmd, String command) { + try { + String rpath = FileSystems.getDefault().getPath(rhome, "bin", rcmd).toString(); + String cpath = FileSystems.getDefault().getPath(command).toRealPath().toString(); + if (cpath.equals(rpath)) { + return true; + } + } catch (IOException ex) { + // should not happen but just return false + } + return false; + } + +} 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 81a02f918888202c7f9cbc30d4b5758a129e9664..4a6ededba9b6103720b5e7d49202ec778b612c6e 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 @@ -37,6 +37,7 @@ import com.oracle.truffle.r.runtime.RChannel; import com.oracle.truffle.r.runtime.RCmdOptions; import com.oracle.truffle.r.runtime.RCmdOptions.Client; import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.RStartParams; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -55,22 +56,28 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; */ public class FastRContext { - private abstract static class CastHelper extends RBuiltinNode { - protected void exprs(CastBuilder casts) { - casts.arg("exprs").asStringVector().mustBe(nullValue().not().and(notEmpty())); + private static final String[] EMPTY = new String[0]; + + private static final class Casts { + private static void exprs(CastBuilder casts) { + casts.arg("exprs").asStringVector().mustBe(notEmpty()); } - protected void kind(CastBuilder casts) { + private static void kind(CastBuilder 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())))); } - protected void args(CastBuilder casts) { - casts.arg("args").asStringVector().mustBe(nullValue().not().and(notEmpty())); + private static void pc(CastBuilder casts) { + casts.arg("pc").asIntegerVector().findFirst().notNA().mustBe(gt(0)); } - protected void pc(CastBuilder casts) { - casts.arg("pc").asIntegerVector().findFirst().notNA().mustBe(gt(0)); + private static void key(CastBuilder casts) { + casts.arg("key").asIntegerVector().mustBe(notEmpty()).findFirst(); + } + + private static void id(CastBuilder casts) { + casts.arg("id").asIntegerVector().mustBe(notEmpty()).findFirst(); } } @@ -89,29 +96,28 @@ public class FastRContext { * {@code .fastr.context.join}. * */ - @RBuiltin(name = ".fastr.context.spawn", kind = PRIMITIVE, parameterNames = {"exprs", "pc", "kind", "args"}, behavior = COMPLEX) - public abstract static class Spawn extends CastHelper { + @RBuiltin(name = ".fastr.context.spawn", kind = PRIMITIVE, parameterNames = {"exprs", "pc", "kind"}, behavior = COMPLEX) + public abstract static class Spawn extends RBuiltinNode { @Override public Object[] getDefaultParameterValues() { - return new Object[]{RMissing.instance, 1, "SHARE_NOTHING", ""}; + return new Object[]{RMissing.instance, 1, "SHARE_NOTHING"}; } @Override protected void createCasts(CastBuilder casts) { - exprs(casts); - pc(casts); - kind(casts); - args(casts); + Casts.exprs(casts); + Casts.pc(casts); + Casts.kind(casts); } @Specialization @TruffleBoundary - protected RIntVector spawn(RAbstractStringVector exprs, int pc, String kind, RAbstractStringVector args) { + protected RIntVector spawn(RAbstractStringVector exprs, int pc, 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++) { - ContextInfo info = createContextInfo(contextKind, args); + ContextInfo info = createContextInfo(contextKind); threads[i] = new RContext.EvalThread(info, RSource.fromTextInternal(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL)); data[i] = info.getId(); } @@ -127,10 +133,11 @@ public class FastRContext { public abstract static class Join extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.arg("handle").asIntegerVector().mustBe(nullValue().not().and(notEmpty())); + casts.arg("handle").asIntegerVector().mustBe(notEmpty()); } @Specialization + @TruffleBoundary protected RNull eval(RAbstractIntVector handle) { try { for (int i = 0; i < handle.getLength(); i++) { @@ -162,70 +169,134 @@ 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", "args"}, behavior = COMPLEX) - public abstract static class Eval extends CastHelper { + @RBuiltin(name = ".fastr.context.eval", kind = PRIMITIVE, parameterNames = {"exprs", "pc", "kind"}, behavior = COMPLEX) + public abstract static class Eval extends RBuiltinNode { @Override public Object[] getDefaultParameterValues() { - return new Object[]{RMissing.instance, 1, "SHARE_NOTHING", ""}; + return new Object[]{RMissing.instance, 1, "SHARE_NOTHING"}; } @Override protected void createCasts(CastBuilder casts) { - exprs(casts); - pc(casts); - kind(casts); - args(casts); + Casts.exprs(casts); + Casts.pc(casts); + Casts.kind(casts); } @Specialization @TruffleBoundary - protected Object eval(RAbstractStringVector exprs, int pc, String kind, RAbstractStringVector args) { + protected Object eval(RAbstractStringVector exprs, int pc, String kind) { RContext.ContextKind contextKind = RContext.ContextKind.valueOf(kind); + Object[] results = new Object[pc]; - // 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++) { - ContextInfo info = createContextInfo(contextKind, args); - threads[i] = new RContext.EvalThread(info, RSource.fromTextInternal(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL)); - } - for (int i = 0; i < pc; i++) { - threads[i].start(); - } - try { + if (pc == 1) { + ContextInfo info = createContextInfo(contextKind); + PolyglotEngine vm = info.createVM(); + results[0] = RContext.EvalThread.run(vm, info, RSource.fromTextInternal(exprs.getDataAt(0), RSource.Internal.CONTEXT_EVAL)); + } 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++) { - threads[i].join(); - results[i] = threads[i].getEvalResult(); + ContextInfo info = createContextInfo(contextKind); + threads[i] = new RContext.EvalThread(info, RSource.fromTextInternal(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL)); + } + for (int i = 0; i < pc; i++) { + threads[i].start(); + } + try { + for (int i = 0; i < pc; i++) { + threads[i].join(); + results[i] = threads[i].getEvalResult(); + } + } catch (InterruptedException ex) { + throw RError.error(this, RError.Message.GENERIC, "error finishing eval thread"); } - } catch (InterruptedException ex) { - throw RError.error(this, RError.Message.GENERIC, "error finishing eval thread"); } return RDataFactory.createList(results); } } - private static ContextInfo createContextInfo(RContext.ContextKind contextKind, RAbstractStringVector args) { - RStartParams startParams = new RStartParams(RCmdOptions.parseArguments(Client.RSCRIPT, args.materialize().getDataCopy(), false), false); - ContextInfo info = ContextInfo.create(startParams, contextKind, RContext.getInstance(), RContext.getInstance().getConsoleHandler()); - return info; + @RBuiltin(name = ".fastr.context.r", kind = PRIMITIVE, visibility = OFF, parameterNames = {"args", "env", "intern"}, behavior = COMPLEX) + public abstract static class R extends RBuiltinNode { + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{RMissing.instance, RMissing.instance, RRuntime.LOGICAL_FALSE}; + } + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("args").allowMissing().mustBe(stringValue()); + casts.arg("env").allowMissing().mustBe(stringValue()); + casts.arg("intern").asLogicalVector().findFirst().map(toBoolean()); + } + + @Specialization + @TruffleBoundary + protected Object r(RAbstractStringVector args, RAbstractStringVector env, boolean intern) { + Object rc = RContext.getRRuntimeASTAccess().rcommandMain(args.materialize().getDataCopy(), env.materialize().getDataCopy(), intern); + return rc; + } + + @Specialization + protected Object r(@SuppressWarnings("unused") RMissing arg, @SuppressWarnings("unused") RMissing env, boolean intern) { + return r(RDataFactory.createEmptyStringVector(), RDataFactory.createEmptyStringVector(), intern); + } + + @Specialization + @TruffleBoundary + protected Object r(@SuppressWarnings("unused") RMissing args, RAbstractStringVector env, boolean intern) { + return r(RDataFactory.createEmptyStringVector(), env, intern); + } } - private abstract static class ChannelCastAdapter extends RBuiltinNode { - protected void key(CastBuilder casts) { - casts.arg("key").asIntegerVector().mustBe(nullValue().not().and(notEmpty())).findFirst(); + @RBuiltin(name = ".fastr.context.rscript", kind = PRIMITIVE, visibility = OFF, parameterNames = {"args", "env", "intern"}, behavior = COMPLEX) + public abstract static class Rscript extends RBuiltinNode { + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{RMissing.instance, RMissing.instance, RRuntime.LOGICAL_FALSE}; + } + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("args").mustBe(stringValue(), RError.Message.GENERIC, "usage: /path/to/Rscript [--options] [-e expr [-e expr2 ...] | file] [args]").asStringVector(); + casts.arg("env").allowMissing().mustBe(stringValue()); + casts.arg("intern").asLogicalVector().findFirst().map(toBoolean()); + } + + @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; } - protected void id(CastBuilder casts) { - casts.arg("id").asIntegerVector().mustBe(nullValue().not().and(notEmpty())).findFirst(); + @Specialization + @TruffleBoundary + 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) { + RStartParams startParams = new RStartParams(RCmdOptions.parseArguments(Client.RSCRIPT, EMPTY, false), false); + ContextInfo info = ContextInfo.create(startParams, null, contextKind, RContext.getInstance(), RContext.getInstance().getConsoleHandler()); + return info; } @RBuiltin(name = ".fastr.channel.create", kind = PRIMITIVE, parameterNames = {"key"}, behavior = COMPLEX) - public abstract static class CreateChannel extends ChannelCastAdapter { + public abstract static class CreateChannel extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - key(casts); + Casts.key(casts); } @Specialization @@ -237,10 +308,10 @@ public class FastRContext { } @RBuiltin(name = ".fastr.channel.get", kind = PRIMITIVE, parameterNames = {"key"}, behavior = COMPLEX) - public abstract static class GetChannel extends ChannelCastAdapter { + public abstract static class GetChannel extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - key(casts); + Casts.key(casts); } @Specialization @@ -252,10 +323,10 @@ public class FastRContext { } @RBuiltin(name = ".fastr.channel.close", visibility = OFF, kind = PRIMITIVE, parameterNames = {"id"}, behavior = COMPLEX) - public abstract static class CloseChannel extends ChannelCastAdapter { + public abstract static class CloseChannel extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - id(casts); + Casts.id(casts); } @Specialization @@ -268,10 +339,10 @@ public class FastRContext { } @RBuiltin(name = ".fastr.channel.send", visibility = OFF, kind = PRIMITIVE, parameterNames = {"id", "data"}, behavior = COMPLEX) - public abstract static class ChannelSend extends ChannelCastAdapter { + public abstract static class ChannelSend extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - id(casts); + Casts.id(casts); } @Specialization @@ -284,10 +355,10 @@ public class FastRContext { } @RBuiltin(name = ".fastr.channel.receive", kind = PRIMITIVE, parameterNames = {"id"}, behavior = COMPLEX) - public abstract static class ChannelReceive extends ChannelCastAdapter { + public abstract static class ChannelReceive extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - id(casts); + Casts.id(casts); } @Specialization @@ -299,10 +370,10 @@ public class FastRContext { } @RBuiltin(name = ".fastr.channel.poll", kind = PRIMITIVE, parameterNames = {"id"}, behavior = COMPLEX) - public abstract static class ChannelPoll extends ChannelCastAdapter { + public abstract static class ChannelPoll extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - id(casts); + Casts.id(casts); } @Specialization @@ -341,4 +412,5 @@ public class FastRContext { } } } + } 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 e58eaf4b62f6fd9328fd27a758c0052a067e6e2b..9ad0b4fcb9612dfdc2063665d27ba7ca639a0a66 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 @@ -27,11 +27,10 @@ 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.TruffleBoundary; -import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.FastROptions; -import com.oracle.truffle.r.runtime.RError; 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; @@ -39,6 +38,11 @@ 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 { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("values").asStringVector(); + } + @Specialization @TruffleBoundary protected RNull debug(RAbstractStringVector vec) { @@ -48,9 +52,4 @@ public abstract class FastRDebug extends RBuiltinNode { return RNull.instance; } - @SuppressWarnings("unused") - @Fallback - protected Object fallback(Object a1) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "element"); - } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRFunctionProfiler.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRFunctionProfiler.java deleted file mode 100644 index 580a10472010aacda10f4bc56192bca9b2f80c1a..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRFunctionProfiler.java +++ /dev/null @@ -1,257 +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.nodes.builtin.fastr; - -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.missingValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; -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.TruffleBoundary; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.nodes.builtin.CastBuilder; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.instrumentation.RFunctionProfiler; -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.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.RStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.tools.Profiler; - -public class FastRFunctionProfiler { - - @RBuiltin(name = ".fastr.profiler.create", visibility = OFF, kind = PRIMITIVE, parameterNames = {"func", "mode"}, behavior = COMPLEX) - public abstract static class Create extends RBuiltinNode { - private static final int COUNTING = 1; - private static final int TIMING = 2; - - @Override - public Object[] getDefaultParameterValues() { - return new Object[]{RMissing.instance, "counting"}; - } - - @Override - protected void createCasts(CastBuilder casts) { - casts.arg("func").mustBe(instanceOf(RFunction.class).or(missingValue())); - - casts.arg("mode").mustBe(stringValue()).asStringVector(); - } - - private int checkMode(RAbstractStringVector modeVec) { - int result = 0; - for (int i = 0; i < modeVec.getLength(); i++) { - String mode = modeVec.getDataAt(i); - switch (mode) { - case "counting": - result |= COUNTING; - break; - case "timing": - result |= TIMING; - break; - default: - throw RError.error(this, RError.Message.GENERIC, "invalid 'mode', one of 'count, timning' expected"); - } - } - return result; - } - - @Specialization - @TruffleBoundary - protected RNull createFunctionProfiler(RFunction function, RAbstractStringVector modeVec) { - int mode = checkMode(modeVec); - if (!function.isBuiltin()) { - RFunctionProfiler.installTimer(function, (mode & COUNTING) != 0, (mode & TIMING) != 0); - } else { - throw RError.error(this, RError.Message.GENERIC, "cannot profile builtin functions"); - } - return RNull.instance; - } - - @Specialization - @TruffleBoundary - protected RNull createFunctionProfiler(@SuppressWarnings("unused") RMissing value, RAbstractStringVector modeVec) { - int mode = checkMode(modeVec); - RFunctionProfiler.installTimer(null, (mode & COUNTING) != 0, (mode & TIMING) != 0); - return RNull.instance; - } - - } - - @RBuiltin(name = ".fastr.profiler.get", kind = PRIMITIVE, parameterNames = {"func", "threshold", "scale"}, behavior = COMPLEX) - public abstract static class Get extends RBuiltinNode { - - private static final RStringVector COLNAMES = RDataFactory.createStringVector(new String[]{"Invocations", "TotalTime", "SelfTime"}, RDataFactory.COMPLETE_VECTOR); - private static final RStringVector ROWNAMES = RDataFactory.createStringVector(new String[]{"Combined", "Interpreted", "Compiled"}, RDataFactory.COMPLETE_VECTOR); - private static final int NCOLS = 3; - private static final int NROWS = 3; - - @Override - protected void createCasts(CastBuilder casts) { - casts.arg("func").mustBe(instanceOf(RFunction.class).or(missingValue())); - - casts.arg("threshold").mustBe(integerValue().or(doubleValue())).asDoubleVector(); - - casts.arg("scale").mustBe(stringValue()).asStringVector(); - } - - @Override - public Object[] getDefaultParameterValues() { - return new Object[]{RMissing.instance, 0.0, "nanos"}; - } - - private void checkScale(String s) throws RError { - if (!(s.equals("nanos") || s.equals("millis") || s.equals("micros") || s.equals("secs"))) { - throw RError.error(this, RError.Message.GENERIC, "invalid scale: one of 'nanos, micros, millis, secs' expected"); - } - } - - @Specialization - @TruffleBoundary - protected Object get(@SuppressWarnings("unused") RMissing value, RAbstractDoubleVector thresholdVec, RAbstractStringVector scaleVec) { - String scale = scaleVec.getDataAt(0); - checkScale(scale); - double threshold = thresholdVec.getDataAt(0); - Profiler.Counter[] counters = RFunctionProfiler.getCounters(); - if (counters == null) { - throw RError.error(this, RError.Message.GENERIC, "profiling not enabled"); - } - ArrayList<RDoubleVector> dataList = new ArrayList<>(); - ArrayList<String> nameList = new ArrayList<>(); - for (int i = 0; i < counters.length; i++) { - Profiler.Counter counter = counters[i]; - if (threshold > 0.0) { - long time = counter.getTotalTime(Profiler.Counter.TimeKind.INTERPRETED_AND_COMPILED); - if (time <= threshold) { - continue; - } - } - dataList.add(getFunctionMatrix(counter, scale)); - nameList.add(counter.getName()); - } - Object[] data = new Object[dataList.size()]; - String[] names = new String[nameList.size()]; - return RDataFactory.createList(dataList.toArray(data), RDataFactory.createStringVector(nameList.toArray(names), RDataFactory.COMPLETE_VECTOR)); - } - - @Specialization - @TruffleBoundary - protected Object get(RFunction function, @SuppressWarnings("unused") RAbstractDoubleVector threshold, RAbstractStringVector scaleVec) { - String scale = scaleVec.getDataAt(0); - checkScale(scale); - if (!function.isBuiltin()) { - Profiler.Counter counter = RFunctionProfiler.getCounter(function); - if (counter == null) { - throw RError.error(this, RError.Message.GENERIC, "profiling not enabled"); - } else { - return getFunctionMatrix(counter, scale); - } - } else { - throw RError.error(this, RError.Message.GENERIC, "cannot profile builtin functions"); - } - } - - private static RDoubleVector getFunctionMatrix(Profiler.Counter counter, String scale) { - double[] data = new double[NROWS * NCOLS]; - boolean isTiming = RFunctionProfiler.isTiming(); - boolean complete = isTiming ? RDataFactory.COMPLETE_VECTOR : RDataFactory.INCOMPLETE_VECTOR; - for (int r = 0; r < NROWS; r++) { - Profiler.Counter.TimeKind timeKind = Profiler.Counter.TimeKind.values()[r]; - for (int c = 0; c < NCOLS; c++) { - int index = c * NROWS + r; - double value = 0.0; - switch (c) { - case 0: - value = counter.getInvocations(timeKind); - break; - case 1: - value = isTiming ? counter.getTotalTime(timeKind) : RRuntime.DOUBLE_NA; - break; - case 2: - value = isTiming ? counter.getSelfTime(timeKind) : RRuntime.DOUBLE_NA; - } - data[index] = c == 0 ? value : scaledTime(scale, value); - } - } - RDoubleVector result = RDataFactory.createDoubleVector(data, complete, new int[]{3, 3}); - Object[] dimNamesData = new Object[2]; - dimNamesData[0] = ROWNAMES; - dimNamesData[1] = COLNAMES; - RList dimNames = RDataFactory.createList(dimNamesData); - result.setDimNames(dimNames); - return result; - } - - private static double scaledTime(String scale, double time) { - if (RRuntime.isNA(time)) { - return time; - } - switch (scale) { - case "nanos": - return time; - case "micros": - return time / 1000.0; - case "millis": - return time / 1000000.0; - case "secs": - return time / 1000000000.0; - default: - throw RInternalError.shouldNotReachHere(); - } - } - } - - @RBuiltin(name = ".fastr.profiler.reset", visibility = OFF, kind = PRIMITIVE, parameterNames = {}, behavior = COMPLEX) - public abstract static class Reset extends RBuiltinNode { - @Specialization - @TruffleBoundary - protected Object reset() { - RFunctionProfiler.reset(); - return RNull.instance; - } - } - - @RBuiltin(name = ".fastr.profiler.clear", visibility = OFF, kind = PRIMITIVE, parameterNames = {}, behavior = COMPLEX) - public abstract static class Clear extends RBuiltinNode { - @Specialization - @TruffleBoundary - protected Object clear() { - RFunctionProfiler.clear(); - return RNull.instance; - } - } -} 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 1dda3508749ac98bfd666025679dccd78199226e..ce5c3dae4dc188754d89052895ff69e884dd5d6c 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 @@ -22,22 +22,30 @@ */ package com.oracle.truffle.r.nodes.builtin.fastr; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notLogicalNA; +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.RVisibility.OFF; +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 java.io.IOException; - import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerAsserts; 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.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.nodes.DirectCallNode; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.r.nodes.builtin.CastBuilder; +import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; @@ -45,6 +53,7 @@ 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.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RTypedValue; @@ -55,8 +64,8 @@ public class FastRInterop { @Override protected void createCasts(CastBuilder casts) { - casts.firstStringWithError(0, Message.INVALID_ARGUMENT, "mimeType"); - casts.firstStringWithError(1, Message.INVALID_ARGUMENT, "source"); + casts.arg("mimeType").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst(); + casts.arg("source").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst(); } protected CallTarget parse(String mimeType, String source) { @@ -64,10 +73,9 @@ public class FastRInterop { Source sourceObject = RSource.fromTextInternal(source, RSource.Internal.EVAL_WRAPPER, mimeType); try { - emitIO(); return RContext.getInstance().getEnv().parse(sourceObject); - } catch (IOException e) { - throw RError.error(this, Message.GENERIC, "Error while parsing: " + e.getMessage()); + } catch (Throwable t) { + throw RError.error(this, Message.GENERIC, "Error while parsing: " + t.getMessage()); } } @@ -77,9 +85,9 @@ public class FastRInterop { @SuppressWarnings("unused") @Specialization(guards = {"cachedMimeType != null", "cachedMimeType.equals(mimeType)", "cachedSource != null", "cachedSource.equals(source)"}) - protected Object evalCached(VirtualFrame frame, String mimeType, String source, // - @Cached("mimeType") String cachedMimeType, // - @Cached("source") String cachedSource, // + protected Object evalCached(VirtualFrame frame, String mimeType, String source, + @Cached("mimeType") String cachedMimeType, + @Cached("source") String cachedSource, @Cached("createCall(mimeType, source)") DirectCallNode call) { return call.call(frame, EMPTY_OBJECT_ARRAY); } @@ -89,42 +97,103 @@ public class FastRInterop { protected Object eval(String mimeType, String source) { return parse(mimeType, source).call(); } - - @SuppressWarnings("unused") - private void emitIO() throws IOException { - } } @RBuiltin(name = ".fastr.interop.export", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name", "value"}, behavior = COMPLEX) public abstract static class Export extends RBuiltinNode { - @Specialization + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("name").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst(); + casts.arg("value").boxPrimitive(); + } + + @Specialization(guards = "!isRMissing(value)") @TruffleBoundary - protected Object exportSymbol(Object name, RTypedValue value) { - String stringName = RRuntime.asString(name); - if (stringName == null) { + protected Object exportSymbol(String name, RTypedValue value) { + if (name == null) { throw RError.error(this, RError.Message.INVALID_ARG_TYPE, "name"); } - RContext.getInstance().getExportedSymbols().put(stringName, value); + RContext.getInstance().getExportedSymbols().put(name, value); return RNull.instance; } + + @Specialization + @TruffleBoundary + protected Object exportSymbol(@SuppressWarnings("unused") String name, @SuppressWarnings("unused") RMissing value) { + throw RError.error(this, 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"); + } } @RBuiltin(name = ".fastr.interop.import", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name"}, behavior = COMPLEX) public abstract static class Import extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("name").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst(); + } + @Specialization @TruffleBoundary - protected Object importSymbol(Object name) { - String stringName = RRuntime.asString(name); - if (stringName == null) { - throw RError.error(this, RError.Message.INVALID_ARG_TYPE, "name"); - } - Object object = RContext.getInstance().getEnv().importSymbol(stringName); + protected Object importSymbol(String name) { + Object object = RContext.getInstance().getEnv().importSymbol(name); if (object == null) { - throw RError.error(this, RError.Message.NO_IMPORT_OBJECT, stringName); + throw RError.error(this, 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 { + + @Child private Node node = com.oracle.truffle.api.interop.Message.HAS_SIZE.createNode(); + + @Specialization + public byte hasSize(VirtualFrame frame, TruffleObject obj) { + return RRuntime.asLogical(ForeignAccess.sendHasSize(node, frame, obj)); + } + } + + @RBuiltin(name = ".fastr.interop.isNull", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX) + public abstract static class IsNull extends RBuiltinNode { + + @Child private Node node = com.oracle.truffle.api.interop.Message.IS_NULL.createNode(); + + @Specialization + public byte hasSize(VirtualFrame frame, TruffleObject obj) { + return RRuntime.asLogical(ForeignAccess.sendIsNull(node, frame, obj)); + } + } + + @RBuiltin(name = ".fastr.interop.isExecutable", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX) + public abstract static class IsExecutable extends RBuiltinNode { + + @Child private Node node = com.oracle.truffle.api.interop.Message.IS_EXECUTABLE.createNode(); + + @Specialization + public byte hasSize(VirtualFrame frame, TruffleObject obj) { + return RRuntime.asLogical(ForeignAccess.sendIsExecutable(node, frame, obj)); + } + } + + @RBuiltin(name = ".fastr.interop.toBoolean", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX) + public abstract static class ToBoolean extends RBuiltinNode { + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("value").mustBe(logicalValue()).asLogicalVector().mustBe(singleElement()).findFirst().mustBe(notLogicalNA()).map(Predef.toBoolean()); + } + + @Specialization + public boolean toBoolean(boolean value) { + return 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 8c70d8e2534bfec03b3a9d25494ef3064b3b5769..22ca9ce3ff3485bf0aeea92b0a71e36678654469 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 @@ -22,14 +22,15 @@ */ package com.oracle.truffle.r.nodes.builtin.fastr; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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 com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -44,16 +45,16 @@ public abstract class FastRStackTrace extends RBuiltinNode { return new Object[]{RRuntime.LOGICAL_FALSE}; } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("print.frame.contents").asLogicalVector().findFirst().map(toBoolean()); + } + + @TruffleBoundary @Specialization - protected RNull printStackTrace(byte printFrameContents) { - boolean printFrameSlots = printFrameContents == RRuntime.LOGICAL_TRUE; - RContext.getInstance().getConsoleHandler().print(Utils.createStackTrace(printFrameSlots)); + protected RNull printStackTrace(boolean printFrameContents) { + RContext.getInstance().getConsoleHandler().print(Utils.createStackTrace(printFrameContents)); return RNull.instance; } - @SuppressWarnings("unused") - @Fallback - protected Object fallback(Object a1) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "print.frame.contents"); - } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..9a25f3ecb67d606a58474392f45ede641fbddc9d --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2016, 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.builtin.fastr; + +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; +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.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; +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.RSource; +import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RAttributes; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RTypedValue; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.RAttributes.AttributeTracer.Change; +import com.oracle.truffle.r.runtime.instrument.InstrumentationState.RprofState; +import com.oracle.truffle.tools.Profiler; +import com.oracle.truffle.tools.Profiler.Counter.TimeKind; + +public class FastRStats { + + private static final class Casts { + private static void filename(CastBuilder casts) { + casts.arg("filename").allowNull().mustBe(stringValue()).asStringVector(); + } + + private static void append(CastBuilder casts) { + casts.arg("append").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).notNA().map(toBoolean()); + } + } + + @RBuiltin(name = ".fastr.prof.attr", visibility = OFF, kind = PRIMITIVE, parameterNames = {"filename", "append"}, behavior = COMPLEX) + public abstract static class FastRProfAttr extends RBuiltinNode implements RAttributes.AttributeTracer.Listener { + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{"Rprofattr.out", RRuntime.LOGICAL_FALSE}; + } + + @Override + protected void createCasts(CastBuilder casts) { + Casts.filename(casts); + Casts.append(casts); + } + + @SuppressWarnings("unused") + @Specialization + @TruffleBoundary + protected RNull profAttr(RNull filenameVec, boolean append) { + endProfiling(); + return RNull.instance; + } + + @Specialization + @TruffleBoundary + protected RNull profAttr(RAbstractStringVector filenameVec, boolean append) { + if (filenameVec.getLength() == 0) { + // disable + endProfiling(); + } else { + // enable after ending any previous session + State state = State.get(); + try { + PrintStream out = new PrintStream(new FileOutputStream(filenameVec.getDataAt(0), append)); + state.setOut(out); + RAttributes.AttributeTracer.addListener(this); + RAttributes.AttributeTracer.setTracingState(true); + } catch (IOException ex) { + throw RError.error(this, RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0))); + } + + } + return RNull.instance; + } + + protected void endProfiling() { + State state = State.get(); + if (state.out() != null) { + state.cleanup(0); + } + } + + @Override + public void reportAttributeChange(Change change, RAttributes attrs, Object value) { + State rprofattrState = State.get(); + rprofattrState.out().printf("%s,%d,", change.name(), System.identityHashCode(attrs)); + switch (change) { + case CREATE: + rprofattrState.out().print("NA"); + break; + case GROW: + rprofattrState.out().printf("%d", (int) value); + break; + default: + rprofattrState.out().printf("%s", (String) value); + break; + } + rprofattrState.out().println(); + } + + private static class State extends RprofState { + private static State get() { + State state = (State) RContext.getInstance().stateInstrumentation.getRprofState("attr"); + if (state == null) { + state = new State(); + RContext.getInstance().stateInstrumentation.setRprofState("attr", state); + } + return state; + } + + @Override + public void cleanup(int status) { + RAttributes.AttributeTracer.setTracingState(false); + closeAndResetOut(); + } + + } + + } + + @RBuiltin(name = ".fastr.stats.typecounts", visibility = OFF, kind = PRIMITIVE, parameterNames = {"filename", "append"}, behavior = COMPLEX) + public abstract static class FastRProfTypecounts extends RBuiltinNode implements RDataFactory.Listener { + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{"Rproftypecounts.out", RRuntime.LOGICAL_FALSE}; + } + + @Override + protected void createCasts(CastBuilder casts) { + Casts.filename(casts); + Casts.append(casts); + } + + @SuppressWarnings("unused") + @Specialization + @TruffleBoundary + protected RNull profTypecounts(RNull filenameVec, boolean append) { + endProfiling(); + return RNull.instance; + } + + @Specialization + @TruffleBoundary + protected RNull profTypecounts(RAbstractStringVector filenameVec, boolean append) { + if (filenameVec.getLength() == 0) { + // disable + endProfiling(); + } else { + // enable after ending any previous session + State state = State.get(); + try { + PrintStream out = new PrintStream(new FileOutputStream(filenameVec.getDataAt(0), append)); + state.setOut(out); + 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))); + } + + } + return RNull.instance; + } + + protected void endProfiling() { + State state = State.get(); + if (state.out() != null) { + RDataFactory.setTracingState(false); + state.cleanup(0); + } + } + + @Override + public void reportAllocation(RTypedValue data) { + Class<? extends RTypedValue> klass = data.getClass(); + boolean isVector = (data instanceof RAbstractVector); + State state = State.get(); + Map<Class<? extends RTypedValue>, SortedMap<Integer, State.Counter>> typecountsMap = state.getTypecountsMap(); + SortedMap<Integer, State.Counter> countsMap = typecountsMap.get(klass); + if (countsMap == null) { + countsMap = new TreeMap<>(); + typecountsMap.put(klass, countsMap); + } + int length; + if (isVector) { + RAbstractVector vector = (RAbstractVector) data; + length = vector.getLength(); + } else { + length = 1; + } + State.Counter count = countsMap.get(length); + if (count == null) { + count = new State.Counter(); + countsMap.put(length, count); + } + count.incCount(); + } + + private static class State extends RprofState { + public static class Counter { + private int count; + + public void incCount() { + count++; + } + + public int getCount() { + return count; + } + + @Override + public String toString() { + return Integer.toString(count); + } + + } + + private Map<Class<? extends RTypedValue>, SortedMap<Integer, Counter>> typecountsMap; + + private static State get() { + State state = (State) RContext.getInstance().stateInstrumentation.getRprofState("typecounts"); + if (state == null) { + state = new State(); + RContext.getInstance().stateInstrumentation.setRprofState("typecounts", state); + } + return state; + } + + private Map<Class<? extends RTypedValue>, SortedMap<Integer, Counter>> getTypecountsMap() { + if (typecountsMap == null) { + typecountsMap = new HashMap<>(); + } + return typecountsMap; + } + + @Override + public void cleanup(int status) { + for (Map.Entry<Class<? extends RTypedValue>, SortedMap<Integer, Counter>> entry : getTypecountsMap().entrySet()) { + SortedMap<Integer, Counter> countsMap = entry.getValue(); + int totalCount = 0; + for (Counter counter : countsMap.values()) { + totalCount += counter.getCount(); + } + out().printf("%s,%d", entry.getKey().getSimpleName(), totalCount); + for (Map.Entry<Integer, Counter> countsEntry : countsMap.entrySet()) { + out().printf(",%d:%d", countsEntry.getKey(), countsEntry.getValue().getCount()); + } + out().println(); + } + closeAndResetOut(); + } + } + + } + + @RBuiltin(name = ".fastr.stats.funcounts", visibility = OFF, kind = PRIMITIVE, parameterNames = {"filename", "append", "timing", "threshold", "histograms"}, behavior = COMPLEX) + public abstract static class FastRProfFuncounts extends RBuiltinNode { + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{"Rproffuncounts.out", RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, 0, RRuntime.LOGICAL_FALSE}; + } + + @Override + protected void createCasts(CastBuilder casts) { + Casts.filename(casts); + Casts.append(casts); + casts.arg("timing").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("threshold").asIntegerVector().findFirst().notNA(); + casts.arg("histograms").asLogicalVector().findFirst().notNA().map(toBoolean()); + } + + @SuppressWarnings("unused") + @Specialization + @TruffleBoundary + protected RNull profFuncounts(RNull filenameVec, boolean append, boolean timing, int threshold, boolean histograms) { + endProfiling(); + return RNull.instance; + } + + @Specialization + @TruffleBoundary + protected RNull profFuncounts(RAbstractStringVector filenameVec, boolean append, boolean timing, int threshold, boolean histograms) { + if (filenameVec.getLength() == 0) { + // disable + endProfiling(); + } else { + // enable after ending any previous session + State state = State.get(); + try { + PrintStream out = new PrintStream(new FileOutputStream(filenameVec.getDataAt(0), append)); + state.initialize(out, threshold, timing, histograms); + Profiler profiler = RContext.getInstance().stateInstrumentation.getProfiler(); + 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))); + } + + } + return RNull.instance; + } + + protected void endProfiling() { + State state = State.get(); + if (state.out() != null) { + state.cleanup(0); + } + } + + private static class State extends RprofState { + private int threshold; + private boolean timing; + private boolean histograms; + + private static State get() { + State state = (State) RContext.getInstance().stateInstrumentation.getRprofState("funcounts"); + if (state == null) { + state = new State(); + RContext.getInstance().stateInstrumentation.setRprofState("funcounts", state); + } + return state; + } + + private void initialize(PrintStream outA, int thresholdA, boolean timingA, boolean histogramsA) { + this.setOut(outA); + this.threshold = thresholdA; + this.timing = timingA; + this.histograms = histogramsA; + } + + @Override + public void cleanup(int status) { + Profiler profiler = RContext.getInstance().getInstrumentationState().getProfiler(); + if (histograms) { + profiler.printHistograms(out()); + return; + } + /* + * Report the statement counts/timing information at the end of the run. The report + * is per function. If timing is on, output is sorted by time, otherwise by + * invocation count. When timing, functions that consumed less time than requested + * threshold (default 0) are not included in the report. + */ + Map<SourceSection, Profiler.Counter> counters = profiler.getCounters(); + long totalTime = 0; + SortableCounter[] sortedCounters = new SortableCounter[counters.size()]; + int i = 0; + for (Profiler.Counter counter : counters.values()) { + sortedCounters[i++] = new SortableCounter(counter, timing); + if (timing) { + totalTime += counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED); + } + } + Arrays.sort(sortedCounters); + for (SortableCounter scounter : sortedCounters) { + long time = scounter.counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED); + long invocations = scounter.counter.getInvocations(TimeKind.INTERPRETED_AND_COMPILED); + boolean include = timing ? time > 0 && time > threshold : invocations > 0; + if (include) { + SourceSection ss = scounter.counter.getSourceSection(); + Source source = ss.getSource(); + out().println("=========="); + out().printf("calls %d", invocations); + if (timing) { + double thisPercent = percent(time, totalTime); + out().printf(", time %d ms (%.2f%%)", time, thisPercent); + } + out().printf(": %s, %s%n", scounter.counter.getName(), RSource.getOrigin(source)); + } + } + profiler.clearData(); + closeAndResetOut(); + } + + private static double percent(long a, long b) { + return ((double) a * 100) / b; + } + + } + + private static final class SortableCounter implements Comparable<SortableCounter> { + private boolean timing; + private Profiler.Counter counter; + + private SortableCounter(Profiler.Counter counter, boolean timing) { + this.counter = counter; + this.timing = timing; + } + + @Override + public int compareTo(SortableCounter other) { + if (timing) { + long myTime = counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED); + long otherTime = other.counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED); + return myTime < otherTime ? 1 : (myTime > otherTime ? -1 : 0); + } else { + long myInvocations = counter.getInvocations(TimeKind.INTERPRETED_AND_COMPILED); + long otherInvocations = other.counter.getInvocations(TimeKind.INTERPRETED_AND_COMPILED); + return myInvocations < otherInvocations ? 1 : (myInvocations > otherInvocations ? -1 : 0); + } + } + + } + + } +} 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 ed3638bc5c18fe145211ffb5c76060e24d55ba65..a56f3e5159b8a69a283ef3cf45d87cc4394b2fed 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.fastr; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; 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.PRIMITIVE; @@ -29,11 +30,11 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import java.io.IOException; 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.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeVisitor; import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; import com.oracle.truffle.r.nodes.instrumentation.RSyntaxTags; @@ -44,7 +45,6 @@ import com.oracle.truffle.r.runtime.conn.StdConnections; import com.oracle.truffle.r.runtime.data.RFunction; 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.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; @@ -76,13 +76,19 @@ public abstract class FastRSyntaxTree extends RBuiltinNode { return new Object[]{RMissing.instance, "rsyntaxnode", RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE}; } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("func").mustBe(instanceOf(RFunction.class)); + casts.arg("visitMode").asStringVector().findFirst(); + casts.arg("printSource").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("printTags").asLogicalVector().findFirst().map(toBoolean()); + } + @Specialization @TruffleBoundary - protected RNull printTree(RFunction function, RAbstractStringVector visitMode, byte printSourceLogical, byte printTagsLogical) { - boolean printSource = RRuntime.fromLogical(printSourceLogical); - boolean printTags = RRuntime.fromLogical(printTagsLogical); + protected RNull printTree(RFunction function, String visitMode, boolean printSource, boolean printTags) { FunctionDefinitionNode root = (FunctionDefinitionNode) function.getTarget().getRootNode(); - switch (visitMode.getDataAt(0)) { + switch (visitMode) { case "node": root.accept(new NodeVisitor() { @@ -184,12 +190,6 @@ public abstract class FastRSyntaxTree extends RBuiltinNode { return result; } - @SuppressWarnings("unused") - @Fallback - protected Object fallback(Object a1, Object a2, Object a3, Object a4) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); - } - private static void printIndent(int depth) { for (int i = 0; i < depth; i++) { writeString(" ", false); 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 8baed140fb8b258b6cce56d78c3dffed53e90fee..c24b8abdd4cc8a7d1f4a1b953ffb178fd0a94769 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 @@ -27,6 +27,7 @@ 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.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.JumpToTopLevelException; import com.oracle.truffle.r.runtime.RError; @@ -34,14 +35,17 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.Utils; 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 = ".fastr.throw", kind = PRIMITIVE, parameterNames = {"name"}, behavior = COMPLEX) public abstract class FastRThrowIt extends RBuiltinNode { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("name").asStringVector().findFirst(); + } + @Specialization @TruffleBoundary - protected RNull throwit(RAbstractStringVector x) { - String name = x.getDataAt(0); + protected RNull throwit(String name) { switch (name) { case "AIX": throw new ArrayIndexOutOfBoundsException(); 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 470f42fd0914c3dffa37ffd4c107dbf93857b17c..c756f3e196471d6c18c114e36d60e044874117e3 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 @@ -43,6 +43,7 @@ import com.oracle.truffle.r.nodes.builtin.base.TraceFunctions; import com.oracle.truffle.r.nodes.builtin.base.TraceFunctionsFactory.PrimTraceNodeGen; import com.oracle.truffle.r.nodes.builtin.base.TraceFunctionsFactory.PrimUnTraceNodeGen; import com.oracle.truffle.r.nodes.builtin.helpers.TraceHandling; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.nodes.unary.CastLogicalNode; import com.oracle.truffle.r.nodes.unary.CastLogicalNodeGen; import com.oracle.truffle.r.runtime.ArgumentsSignature; @@ -50,7 +51,6 @@ 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.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.RLanguage; @@ -77,7 +77,7 @@ public class FastRTrace { topEnv = insert(TopEnvNodeGen.create(null)); parentFrame = insert(ParentFrameNodeGen.create(null)); } - return topEnv.execute(frame, parentFrame.execute(frame, 1), RNull.instance); + return topEnv.executeBuiltin(frame, parentFrame.execute(frame, 1), RNull.instance); } protected Object getFunction(VirtualFrame frame, Object what, Object where) { @@ -85,7 +85,7 @@ public class FastRTrace { CompilerDirectives.transferToInterpreterAndInvalidate(); getNode = insert(GetNodeGen.create(null)); } - return getNode.execute(frame, what, where, RType.Function.getName(), true); + return getNode.executeBuiltin(frame, what, where, RType.Function.getName(), true); } protected void checkWhat(Object what) { @@ -114,6 +114,7 @@ public class FastRTrace { @Child private TraceFunctions.PrimTrace primTrace; @Child private CastLogicalNode castLogical; + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); @Specialization protected Object trace(VirtualFrame frame, Object whatObj, Object tracer, Object exit, Object at, Object printObj, Object signature, Object whereObj) { @@ -136,8 +137,8 @@ public class FastRTrace { primTrace = insert(PrimTraceNodeGen.create(null)); } - Object result = primTrace.execute(frame, func); - RContext.getInstance().setVisible(false); + Object result = primTrace.executeBuiltin(frame, func); + visibility.execute(frame, false); return result; } @@ -153,7 +154,7 @@ public class FastRTrace { print = RRuntime.fromLogical((byte) castLogical.execute(printObj)); } complexCase(func, tracer, exit, at, print, signature); - RContext.getInstance().setVisible(true); + visibility.execute(frame, true); return func.toString(); } @@ -181,7 +182,6 @@ public class FastRTrace { @Specialization protected Object untrace(VirtualFrame frame, Object whatObj, Object signature, Object whereObj) { - RContext.getInstance().setVisible(false); Object what = whatObj; checkWhat(what); Object where = whereObj; @@ -198,7 +198,7 @@ public class FastRTrace { CompilerDirectives.transferToInterpreterAndInvalidate(); primUnTrace = insert(PrimUnTraceNodeGen.create(null)); } - primUnTrace.execute(frame, func); + primUnTrace.executeBuiltin(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 be5c0add5012747bd87559163cab6ff6cfbdafc9..01682e5fbdd37758b76dae86366ea339ad2bc5b8 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 @@ -22,16 +22,18 @@ */ 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.nodes.builtin.CastBuilder.Predef.toBoolean; 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.PRIMITIVE; -import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.NodeUtil; import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; 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.RFunction; @@ -44,17 +46,19 @@ public abstract class FastRTree extends RBuiltinNode { return new Object[]{RMissing.instance, RRuntime.LOGICAL_FALSE}; } + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("func").mustBe(instanceOf(RFunction.class)); + casts.arg("verbose").asLogicalVector().findFirst().map(toBoolean()); + + } + @Specialization - protected String printTree(RFunction function, byte verbose) { + @TruffleBoundary + protected String printTree(RFunction function, boolean verbose) { RootNode root = function.getTarget().getRootNode(); - String printedTree = verbose == RRuntime.LOGICAL_TRUE ? NodeUtil.printTreeToString(root) : NodeUtil.printCompactTreeToString(root); + String printedTree = verbose ? NodeUtil.printTreeToString(root) : NodeUtil.printCompactTreeToString(root); System.out.println(printedTree); return printedTree; } - - @SuppressWarnings("unused") - @Fallback - protected Object fallback(Object a1, Object a2) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); - } } 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 35cd80b4af5e7dd96c2554d5c5831590d52952e6..07719a305b4ca2937b7dbd2d4a5cb64eddebc9b0 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 @@ -19,6 +19,7 @@ import java.util.Arrays; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastDoubleNode; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -45,6 +46,18 @@ public abstract class FastrDqrls extends RBuiltinNode { private final RAttributeProfiles xAttributeProfiles = RAttributeProfiles.create(); private final RAttributeProfiles residualsAttributesProfiles = RAttributeProfiles.create(); + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").asDoubleVector(true, true, true); + casts.arg("n").asIntegerVector().findFirst(); + casts.arg("p").asIntegerVector().findFirst(); + casts.arg("y").asDoubleVector(true, true, true); + casts.arg("ny").asIntegerVector().findFirst(); + casts.arg("tol").asDoubleVector().findFirst(); + casts.arg("coeff").asDoubleVector(true, true, true); + + } + @Specialization public RList doDouble(RAbstractDoubleVector xVec, int n, int p, RAbstractDoubleVector yVec, int ny, double tol, RAbstractDoubleVector coeffVec) { return call(xVec, xVec.materialize(), n, p, yVec, yVec.materialize(), ny, tol, 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 6f4d154672217f2e9c6283836df8b593987500af..044773513f6598af456b3be185fda9108d69737c 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 @@ -23,17 +23,21 @@ package com.oracle.truffle.r.nodes.builtin.helpers; 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.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.r.runtime.JumpToTopLevelException; import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.RSrcref; import com.oracle.truffle.r.runtime.ReturnException; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.context.ConsoleHandler; +import com.oracle.truffle.r.runtime.context.Engine.IncompleteSourceException; import com.oracle.truffle.r.runtime.context.Engine.ParseException; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RFunction; @@ -43,7 +47,9 @@ 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.instrument.InstrumentationState.BrowserState; +import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; /** * The interactive component of the {@code browser} function. @@ -70,13 +76,19 @@ public abstract class BrowserInteractNode extends RNode { ConsoleHandler ch = RContext.getInstance().getConsoleHandler(); BrowserState browserState = RContext.getInstance().stateInstrumentation.getBrowserState(); String savedPrompt = ch.getPrompt(); - ch.setPrompt(browserPrompt(RArguments.getDepth(frame))); - RFunction caller = RArguments.getFunction(frame); - boolean callerIsDebugged = DebugHandling.isDebugged(caller); + RFunction callerFunction = RArguments.getFunction(frame); + // we may be at top level where there is not caller + boolean callerIsDebugged = callerFunction == null ? false : DebugHandling.isDebugged(callerFunction); int exitMode = NEXT; + RCaller currentCaller = RArguments.getCall(mFrame); + if (currentCaller == null) { + currentCaller = RCaller.topLevel; + } + RCaller browserCaller = createCaller(currentCaller); try { - browserState.setInBrowser(true); + browserState.setInBrowser(browserCaller); LW: while (true) { + ch.setPrompt(browserPrompt(RArguments.getDepth(frame))); String input = ch.readLine(); if (input != null) { input = input.trim(); @@ -94,15 +106,17 @@ public abstract class BrowserInteractNode extends RNode { break LW; case "n": exitMode = NEXT; + // don't enable debugging if at top level if (!callerIsDebugged) { - DebugHandling.enableDebug(caller, "", "", true, true); + DebugHandling.enableDebug(callerFunction, "", "", true, true); } browserState.setLastEmptyLineCommand("n"); break LW; case "s": exitMode = STEP; + // don't enable debugging if at top level if (!callerIsDebugged) { - DebugHandling.enableDebug(caller, "", "", true, true); + DebugHandling.enableDebug(callerFunction, "", "", true, true); } browserState.setLastEmptyLineCommand("s"); break LW; @@ -129,24 +143,42 @@ public abstract class BrowserInteractNode extends RNode { } default: - try { - RContext.getEngine().parseAndEval(RSource.fromTextInternal(input, RSource.Internal.BROWSER_INPUT), mFrame, true); - } catch (ReturnException e) { - exitMode = NEXT; - break LW; - } catch (ParseException e) { - throw e.throwAsRError(); + StringBuffer sb = new StringBuffer(input); + while (true) { + try { + RContext.getEngine().parseAndEval(RSource.fromTextInternal(sb.toString(), RSource.Internal.BROWSER_INPUT), mFrame, true); + } catch (IncompleteSourceException e) { + // read another line of input + ch.setPrompt("+ "); + sb.append(ch.readLine()); + // The only continuation in the while loop + continue; + } catch (ParseException e) { + e.report(ch); + continue LW; + } catch (RError e) { + continue LW; + } catch (ReturnException e) { + exitMode = NEXT; + break LW; + } + continue LW; } - break; } } } finally { ch.setPrompt(savedPrompt); - browserState.setInBrowser(false); + browserState.setInBrowser(null); } return exitMode; } + @TruffleBoundary + private static RCaller createCaller(RCaller currentCaller) { + RCodeBuilder<RSyntaxNode> builder = RContext.getASTBuilder(); + return RCaller.create(null, currentCaller, builder.call(RSyntaxNode.INTERNAL, builder.lookup(RSyntaxNode.INTERNAL, "browser", true))); + } + private static String getSrcinfo(RStringVector element) { Object srcref = element.getAttr(RRuntime.R_SRCREF); if (srcref != null) { 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 799fa83b5bd2f153efc32738aee19ed16c462890..514c608b84adf4c87d6b43b49493632414f4d57e 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 @@ -26,7 +26,9 @@ import java.io.IOException; import java.util.ArrayList; import com.oracle.truffle.api.Assumption; +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.instrumentation.EventBinding; import com.oracle.truffle.api.instrumentation.EventContext; @@ -142,6 +144,7 @@ public class DebugHandling { attachDebugHandler(RInstrumentation.getFunctionDefinitionNode(func), text, condition, once, implicit); } + @TruffleBoundary private static FunctionStatementsEventListener attachDebugHandler(FunctionDefinitionNode fdn, Object text, Object condition, boolean once, boolean implicit) { FunctionStatementsEventListener fser = new FunctionStatementsEventListener(fdn, text, condition, once, implicit); // First attach the main listener on the START_FUNCTION @@ -222,6 +225,7 @@ public class DebugHandling { } } + @TruffleBoundary protected static void print(String msg, boolean nl) { try { StdConnections.getStdout().writeString(msg, nl); @@ -244,8 +248,7 @@ public class DebugHandling { * so hopefully only the one function will actually get instrumented - but * will everything get invalidated? */ - stepIntoInstrument = RInstrumentation.getInstrumenter().attachListener(SourceSectionFilter.newBuilder().tagIs(StandardTags.RootTag.class).build(), - new StepIntoInstrumentListener(getFunctionStatementsEventListener(functionDefinitionNode))); + attachStepInto(); } break; case BrowserInteractNode.CONTINUE: @@ -267,11 +270,19 @@ public class DebugHandling { } } + @TruffleBoundary + private void attachStepInto() { + stepIntoInstrument = RInstrumentation.getInstrumenter().attachListener(SourceSectionFilter.newBuilder().tagIs(StandardTags.RootTag.class).build(), + new StepIntoInstrumentListener(getFunctionStatementsEventListener(functionDefinitionNode))); + + } + private void doContinue() { FunctionStatementsEventListener fser = getFunctionStatementsEventListener(functionDefinitionNode); fser.setContinuing(); } + @TruffleBoundary protected void clearStepInstrument() { if (stepIntoInstrument != null) { stepIntoInstrument.dispose(); @@ -376,6 +387,7 @@ public class DebugHandling { @Override public void onEnter(EventContext context, VirtualFrame frame) { if (!disabled()) { + CompilerDirectives.transferToInterpreter(); print("debugging in: ", false); printCall(frame); /* @@ -392,6 +404,7 @@ public class DebugHandling { @Override public void onReturnValue(EventContext context, VirtualFrame frame, Object result) { if (!disabled()) { + CompilerDirectives.transferToInterpreter(); returnCleanup(frame); } } @@ -399,6 +412,7 @@ public class DebugHandling { @Override public void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) { if (!disabled()) { + CompilerDirectives.transferToInterpreter(); returnCleanup(frame); } } @@ -425,6 +439,7 @@ public class DebugHandling { } } + @TruffleBoundary private static void printNode(Node node, boolean startFunction) { ConsoleHandler consoleHandler = RContext.getInstance().getConsoleHandler(); /* @@ -457,6 +472,7 @@ public class DebugHandling { @Override public void onEnter(EventContext context, VirtualFrame frame) { if (!disabled()) { + CompilerDirectives.transferToInterpreter(); // in case we did a step into that never called a function clearStepInstrument(); RBaseNode node = (RBaseNode) context.getInstrumentedNode(); @@ -508,6 +524,7 @@ public class DebugHandling { @Override public void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) { if (!disabled()) { + CompilerDirectives.transferToInterpreter(); returnCleanup(); } } @@ -515,6 +532,7 @@ public class DebugHandling { @Override public void onReturnValue(EventContext context, VirtualFrame frame, Object result) { if (!disabled()) { + CompilerDirectives.transferToInterpreter(); returnCleanup(); } } @@ -551,6 +569,7 @@ public class DebugHandling { @Override public void onEnter(EventContext context, VirtualFrame frame) { if (!RContext.getInstance().stateInstrumentation.debugGloballyDisabled()) { + CompilerDirectives.transferToInterpreter(); FunctionDefinitionNode fdn = (FunctionDefinitionNode) context.getInstrumentedNode().getRootNode(); ensureSingleStep(fdn); functionStatementsEventListener.clearStepInstrument(); 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 49eb4e95d80c27d4a46bcb8a641ce011bb515e4d..7b85116832f9cdf20d51f6aca30920ca7b9f7869 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 @@ -26,6 +26,7 @@ import java.io.FileWriter; import java.io.IOException; 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.instrumentation.EventBinding; import com.oracle.truffle.api.instrumentation.EventContext; @@ -148,12 +149,17 @@ public class TraceHandling { RCaller caller = RArguments.getCall(frame); String callString; if (caller != null) { - callString = RContext.getRRuntimeASTAccess().getCallerSource(caller); + callString = getCallerSource(caller); } else { callString = "<no source>"; } return callString; } + + @TruffleBoundary + private static String getCallerSource(RCaller caller) { + return RContext.getRRuntimeASTAccess().getCallerSource(caller); + } } /** @@ -172,7 +178,7 @@ public class TraceHandling { String callString = getCallSource(frame); outputHandler.writeString("trace: " + callString, true); } catch (IOException ex) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, ex.getMessage()); + throw RError.ioError(RError.SHOW_CALLER2, ex); } } } @@ -207,7 +213,7 @@ public class TraceHandling { String callString = getCallSource(frame); outputHandler.writeString("Tracing " + callString + " on entry", true); } catch (IOException ex) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, ex.getMessage()); + throw RError.ioError(RError.SHOW_CALLER2, ex); } } RContext.getEngine().eval(tracer, frame.materialize()); @@ -255,6 +261,7 @@ public class TraceHandling { private static class StdoutOutputHandler extends OutputHandler { @Override + @TruffleBoundary void writeString(String s, boolean nl) throws IOException { StdConnections.getStdout().writeString(s, nl); } @@ -272,6 +279,7 @@ public class TraceHandling { } @Override + @TruffleBoundary void writeString(String s, boolean nl) throws IOException { fileWriter.append(s); if (nl) { diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/access/vector/StringSearchNodeTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/access/vector/StringSearchNodeTest.java index b7fb90d88d183f3032feee11a018343b5a215545..3e31668bda6e21cd082f9d5065137cd0c2699665 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/access/vector/StringSearchNodeTest.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/access/vector/StringSearchNodeTest.java @@ -115,7 +115,7 @@ public class StringSearchNodeTest extends TestBase { handle = createHandle(SearchFirstStringNode.createNode(true, false), // (node, args) -> { RAbstractStringVector target = (RAbstractStringVector) args[0]; - return node.apply(target, (RAbstractStringVector) args[1], target.getLength()); + return node.apply(target, (RAbstractStringVector) args[1], target.getLength(), null); }); } 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/builtin/CastBuilderTest.java index a7835b6c048720307b08440201cdf3df53c1bcc9..e5261bd109bb11571b37481454a1b7fe477a7aaf 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/builtin/CastBuilderTest.java @@ -22,37 +22,46 @@ */ package com.oracle.truffle.r.nodes.builtin; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.elementAt; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asStringVector; +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; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asLogicalVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asStringVector; +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.complexValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.defaultValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.equalTo; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.dimGt; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleNA; +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.emptyStringVector; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt0; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte; 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.isFractional; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalTrue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; 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.mustBe; +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; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.scalarLogicalValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.scalarStringValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.shouldBe; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement; +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.builtin.CastBuilder.Predef.trueValue; -import static com.oracle.truffle.r.nodes.casts.CastUtils.samples; +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; import static org.junit.Assert.fail; import java.util.function.Function; @@ -62,46 +71,62 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import com.oracle.truffle.api.TruffleLanguage; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.RootNode; -import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen; -import com.oracle.truffle.r.nodes.builtin.ArgumentFilter.ArgumentTypeFilter; -import com.oracle.truffle.r.nodes.builtin.ArgumentFilter.ArgumentValueFilter; -import com.oracle.truffle.r.nodes.builtin.CastBuilder.InitialPhaseBuilder; import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; -import com.oracle.truffle.r.nodes.builtin.base.IsNA; -import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler; +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.PredefFiltersSamplers; -import com.oracle.truffle.r.nodes.casts.PredefMappersSamplers; +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.ValuePredicateArgumentFilterSampler; 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; 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.RComplex; +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.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RInteger; 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.model.RAbstractIntVector; +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; +/** + * Tests the cast pipelines and also that the samples generation process matches the intended + * semantics. + */ public class CastBuilderTest { + /** + * The sampler at the moment does not generate any samples for pipelines that do not have any + * filter. + */ + private static final boolean NO_FILTER_EXPECT_EMPTY_SAMPLES = true; + + private static final boolean TEST_SAMPLING = false; + private CastBuilder cb; + private PreinitialPhaseBuilder<Object> arg; + + static { + if (TEST_SAMPLING) { + PipelineConfig.setFilterFactory(FilterSamplerFactory.INSTANCE); + PipelineConfig.setMapperFactory(MapperSamplerFactory.INSTANCE); + } + CastNode.testingMode(); + } @Before public void setUp() { - CastBuilder.Predef.setPredefFilters(new PredefFiltersSamplers()); - CastBuilder.Predef.setPredefMappers(new PredefMappersSamplers()); - cb = new CastBuilder(null); + cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class)); + arg = cb.arg("x"); } @After @@ -111,470 +136,344 @@ public class CastBuilderTest { @Test public void testError() { - cb.arg(0).mustBe( - ValuePredicateArgumentFilterSampler.fromLambdaWithResTypes(x -> x instanceof String, String.class), - RError.Message.DLL_LOAD_ERROR, Function.identity(), "123"); + arg.mustBe(instanceOf(String.class), RError.Message.DLL_LOAD_ERROR, Function.identity(), "123"); + assertCastPreserves("A"); + assertCastFail(Boolean.FALSE, "unable to load shared object 'false'\n 123"); testPipeline(); - - assertEquals("A", cast("A")); - try { - cast(Boolean.FALSE); - fail(); - } catch (IllegalArgumentException e) { - assertEquals("unable to load shared object 'false'\n 123", e.getMessage()); - } - } @Test public void testErrorWithAttachedPredicate() { - cb.arg(0).mustBe(ValuePredicateArgumentFilterSampler.fromLambdaWithResTypes(x -> x instanceof RAbstractIntVector || x instanceof Integer, Object.class), Message.SEED_NOT_VALID_INT); + arg.mustBe(integerValue(), Message.SEED_NOT_VALID_INT); + assertCastPreserves(RDataFactory.createIntVectorFromScalar(1)); + assertCastFail(Boolean.FALSE, RError.Message.SEED_NOT_VALID_INT.message); testPipeline(); - - RAbstractIntVector v = RDataFactory.createIntVectorFromScalar(1); - assertEquals(v, cast(v)); - try { - cast(Boolean.FALSE); - fail(); - } catch (IllegalArgumentException e) { - assertEquals(RError.Message.SEED_NOT_VALID_INT.message, e.getMessage()); - } } @Test public void testWarning() { - cb.arg(0).shouldBe(ValuePredicateArgumentFilterSampler.fromLambdaWithResTypes(x -> x instanceof String, Object.class), RError.Message.DLL_LOAD_ERROR, Function.identity(), "123"); - testPipeline(); - - assertEquals("A", cast("A")); - assertEquals(Boolean.FALSE, cast(Boolean.FALSE)); - // assertEquals("unable to load shared object 'false'\n 123", out.toString()); + arg.shouldBe(instanceOf(String.class), RError.Message.DLL_LOAD_ERROR, Function.identity(), "123"); + assertCastPreserves("A"); + assertCastWarning(Boolean.FALSE, cast(Boolean.FALSE), "unable to load shared object 'false'\n 123"); + testPipeline(NO_FILTER_EXPECT_EMPTY_SAMPLES); } @Test public void testWarningWithAttachedPredicate() { - cb.arg(0).shouldBe(integerValue(), Message.SEED_NOT_VALID_INT); - testPipeline(); - - RAbstractIntVector v = RDataFactory.createIntVectorFromScalar(1); - assertEquals(v, cast(v)); - assertEquals(Boolean.FALSE, cast(Boolean.FALSE)); - // assertEquals(RError.Message.SEED_NOT_VALID_INT.message, out.toString()); + arg.shouldBe(integerValue(), Message.SEED_NOT_VALID_INT); + assertCastPreserves(RDataFactory.createIntVectorFromScalar(1)); + assertCastWarning(Boolean.FALSE, cast(Boolean.FALSE), RError.Message.SEED_NOT_VALID_INT.message); + testPipeline(NO_FILTER_EXPECT_EMPTY_SAMPLES); } @Test public void testDefaultError() { - cb.arg(0, "arg0").mustBe(ValuePredicateArgumentFilterSampler.fromLambdaWithSamples(x -> false, samples(), samples(true, false), Boolean.class)); - testPipeline(false); - - try { - cast(Boolean.FALSE); - fail(); - } catch (IllegalArgumentException e) { - assertEquals(String.format(RError.Message.INVALID_ARGUMENT.message, "arg0"), e.getMessage()); - } + arg.mustBe(atomicLogicalValue().and(logicalTrue())); + assertCastFail(RRuntime.LOGICAL_FALSE, String.format(RError.Message.INVALID_ARGUMENT.message, "x")); + testPipeline(true); } @Test public void testIsInteger() { - cb.arg(0).mustBe(integerValue(), RError.Message.SEED_NOT_VALID_INT); + arg.mustBe(integerValue(), RError.Message.SEED_NOT_VALID_INT); + assertCastPreserves(1, RDataFactory.createIntVectorFromScalar(1)); + assertCastFail("x", RError.Message.SEED_NOT_VALID_INT.message); testPipeline(); - - RAbstractIntVector v = RDataFactory.createIntVectorFromScalar(1); - assertEquals(v, cast(v)); - assertEquals(1, cast(1)); - try { - cast("x"); - fail(); - } catch (IllegalArgumentException e) { - assertEquals(RError.Message.SEED_NOT_VALID_INT.message, e.getMessage()); - } } @Test public void testIsNumericOrComplex() { - cb.arg(0).mustBe(numericValue().or(complexValue()), RError.Message.SEED_NOT_VALID_INT); - testPipeline(); + arg.mustBe(numericValue().or(complexValue()), RError.Message.SEED_NOT_VALID_INT); - assertEquals(1, cast(1)); - assertEquals(RRuntime.LOGICAL_FALSE, cast(RRuntime.LOGICAL_FALSE)); - assertEquals(1.3d, cast(1.3d)); - RComplex c = RDataFactory.createComplex(1, 2); - assertEquals(c, cast(c)); - - Object v = RDataFactory.createIntVectorFromScalar(1); - assertEquals(v, cast(v)); - v = RDataFactory.createLogicalVectorFromScalar(RRuntime.LOGICAL_FALSE); - assertEquals(v, cast(v)); - v = RDataFactory.createDoubleVectorFromScalar(1.2); - assertEquals(v, cast(v)); - v = RDataFactory.createComplexVectorFromScalar(c); - assertEquals(v, cast(v)); + assertCastPreserves(1, RRuntime.LOGICAL_FALSE, 1.3d, RDataFactory.createComplex(1, 2), RDataFactory.createIntVectorFromScalar(1)); + assertCastPreserves(RDataFactory.createLogicalVectorFromScalar(RRuntime.LOGICAL_FALSE), RDataFactory.createDoubleVectorFromScalar(1.2)); + assertCastPreserves(RDataFactory.createComplexVectorFromScalar(RDataFactory.createComplex(1, 2))); - try { - cast("x"); - fail(); - } catch (IllegalArgumentException e) { - assertEquals(RError.Message.SEED_NOT_VALID_INT.message, e.getMessage()); - } + assertCastFail("x", RError.Message.SEED_NOT_VALID_INT.message); + testPipeline(); } @Test public void testAsInteger() { - cb.arg(0).asIntegerVector(); - testPipeline(); + arg.asIntegerVector(); - assertEquals(1, cast(1)); + assertCastPreserves(1, -2, RRuntime.INT_NA); assertEquals(0, cast(RRuntime.LOGICAL_FALSE)); assertEquals(1, cast(1.3d)); - RComplex c = RDataFactory.createComplex(1, 0); - assertEquals(1, cast(c)); + assertEquals(42, cast("42")); + assertEquals(1, cast(RDataFactory.createComplex(1, 0))); + assertEquals(RNull.instance, cast(RNull.instance)); + assertEquals(RMissing.instance, cast(RMissing.instance)); + testPipeline(NO_FILTER_EXPECT_EMPTY_SAMPLES); } @Test public void testAsDouble() { - cb.arg(0).asDoubleVector(); - testPipeline(); + arg.asDoubleVector(); - assertEquals(1.2, cast(1.2)); + assertCastPreserves(1.2, RRuntime.DOUBLE_NA, Double.NaN, Double.POSITIVE_INFINITY); + assertEquals(1.0, cast(RRuntime.LOGICAL_TRUE)); + assertEquals(1.0, cast("1")); + assertEquals(RRuntime.DOUBLE_NA, cast(RRuntime.INT_NA)); + assertEquals(RNull.instance, cast(RNull.instance)); + assertEquals(RMissing.instance, cast(RMissing.instance)); + testPipeline(); } @Test public void testAsLogical() { - cb.arg(0).asLogicalVector(); - testPipeline(); + arg.asLogicalVector(); + assertCastPreserves(RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA); assertEquals(RRuntime.LOGICAL_TRUE, cast(1.2)); + assertEquals(RNull.instance, cast(RNull.instance)); + assertEquals(RRuntime.LOGICAL_NA, cast(RRuntime.INT_NA)); + assertEquals(RMissing.instance, cast(RMissing.instance)); + testPipeline(NO_FILTER_EXPECT_EMPTY_SAMPLES); } @Test public void testAsString() { - cb.arg(0).asStringVector(); - testPipeline(); + arg.asStringVector(); assertEquals("1.2", cast(1.2)); + assertEquals("TRUE", cast(RRuntime.LOGICAL_TRUE)); + assertEquals("FALSE", cast(RRuntime.LOGICAL_FALSE)); + assertEquals("NA", cast(RRuntime.LOGICAL_NA)); + assertEquals("NA", cast(RRuntime.INT_NA)); + assertEquals(RNull.instance, cast(RNull.instance)); + assertEquals(RMissing.instance, cast(RMissing.instance)); + testPipeline(NO_FILTER_EXPECT_EMPTY_SAMPLES); } @Test - public void testEmptyError() { - cb.arg(0, "x").asIntegerVector().mustBe(notEmpty()); - testPipeline(); - - try { - cast(RDataFactory.createIntVector(0)); - } catch (IllegalArgumentException e) { - assertEquals(String.format(RError.Message.INVALID_ARGUMENT.message, "x"), e.getMessage()); - } + public void testAsVector() { + // Note: unlike asXYZVector, asVector always converts to a vector, even scalar values + arg.asVector(); + assertCastPreserves(RNull.instance, RMissing.instance); + testAsVectorBase(); } @Test - public void testEmptyErrorWithCustomMessage() { - cb.arg(0).asIntegerVector().mustBe(notEmpty(), RError.Message.SEED_NOT_VALID_INT); - testPipeline(); + public void testAsVectorWithPreserveNonVectorEqualToFalse() { + // preserveNonVector is true by default + arg.asVector(/* preserveNonVector: */false); - try { - cast(RDataFactory.createIntVector(0)); - } catch (IllegalArgumentException e) { - assertEquals(RError.Message.SEED_NOT_VALID_INT.message, e.getMessage()); - } - } + Object result = cast(RNull.instance); + assertTrue(result instanceof RList); + assertTrue(((RList) result).getLength() == 0); - @Test - public void testSizeWarning() { - cb.arg(0).defaultWarning(RError.Message.LENGTH_GT_1).asIntegerVector().shouldBe(singleElement()); - testPipeline(); + result = cast(RMissing.instance); + assertTrue(result instanceof RList); + assertTrue(((RList) result).getLength() == 0); - cast(RDataFactory.createIntVector(new int[]{1, 2}, true)); - // assertEquals(RError.Message.LENGTH_GT_1.message, out.toString()); + testAsVectorBase(); + } + + private void testAsVectorBase() { + assertVectorEquals(RDataFactory.createIntVectorFromScalar(1), cast(1)); + assertVectorEquals(RDataFactory.createDoubleVectorFromScalar(1), cast(1.0)); + assertCastPreserves(RDataFactory.createStringVector(new String[]{"a", "b"}, true)); + testPipeline(NO_FILTER_EXPECT_EMPTY_SAMPLES); } @Test - public void testSizeWarningWithCustomMessage() { - cb.arg(0).asIntegerVector().shouldBe(singleElement(), RError.Message.SEED_NOT_VALID_INT); + public void testEmptyError() { + arg.asIntegerVector().mustBe(notEmpty()); + assertCastPreserves(RDataFactory.createIntVector(new int[]{42, 1}, true)); + assertCastFail(RDataFactory.createIntVector(0), String.format(RError.Message.INVALID_ARGUMENT.message, "x")); testPipeline(); - - cast(RDataFactory.createIntVector(new int[]{1, 2}, true)); - // assertEquals(RError.Message.SEED_NOT_VALID_INT.message, out.toString()); + // TODO: error in the sampler } @Test - public void testFindFirst() { - cb.arg(0).asIntegerVector().findFirst(0); - testPipeline(); + public void testEmptyErrorWithCustomMessage() { + arg.asIntegerVector().mustBe(notEmpty(), RError.Message.SEED_NOT_VALID_INT); + assertCastFail(RDataFactory.createIntVector(0), Message.SEED_NOT_VALID_INT.message); + } - assertEquals(1, cast(1)); - assertEquals(1, cast(RDataFactory.createIntVector(new int[]{1, 2}, true))); - assertEquals(1, cast("1")); - assertEquals(0, cast(RDataFactory.createIntVector(0))); + @Test + public void testSizeWarning() { + arg.defaultWarning(SHOW_CALLER, 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); } @Test public void testFindFirstWithDefaultValue() { - cb.arg(0).asIntegerVector().findFirst(-1); - testPipeline(); + arg.asIntegerVector().findFirst(42); + assertEquals(42, cast(RNull.instance)); + assertEquals(42, cast(RMissing.instance)); assertEquals(1, cast(1)); assertEquals(1, cast(RDataFactory.createIntVector(new int[]{1, 2}, true))); assertEquals(1, cast("1")); - assertEquals(-1, cast(RDataFactory.createIntVector(0))); + assertEquals(42, cast(RDataFactory.createIntVector(0))); + assertEquals(42, cast(RDataFactory.createList())); + testPipeline(NO_FILTER_EXPECT_EMPTY_SAMPLES); } @Test - public void testFindFirstThrow() { - cb.arg(0).asIntegerVector().mustBe(notEmpty(), RError.Message.SEED_NOT_VALID_INT).findFirst(); - testPipeline(); + public void testFindFirstWithDefaultError() { + // findFirst takes the explicitly specified default error from pipeline + arg.asIntegerVector().defaultError(SHOW_CALLER, RError.Message.SEED_NOT_VALID_INT).findFirst(); + assertCastFail(RNull.instance, Message.SEED_NOT_VALID_INT.message); + } + + @Test + 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"); assertEquals(1, cast(1)); assertEquals(1, cast(RDataFactory.createIntVector(new int[]{1, 2}, true))); assertEquals(1, cast("1")); - try { - cast(RDataFactory.createIntVector(0)); - } catch (IllegalArgumentException e) { - assertEquals(RError.Message.SEED_NOT_VALID_INT.message, e.getMessage()); - } + testPipeline(NO_FILTER_EXPECT_EMPTY_SAMPLES); } @Test public void testNoLogicalNA() { - cb.arg(0).asLogicalVector().findFirst().notNA(RRuntime.LOGICAL_TRUE); - testPipeline(); + arg.asLogicalVector().findFirst().notNA(RRuntime.LOGICAL_TRUE); + assertCastPreserves(RRuntime.LOGICAL_FALSE); assertEquals(RRuntime.LOGICAL_TRUE, cast(RRuntime.LOGICAL_NA)); + testPipeline(); } @Test public void testNoIntegerNA() { - cb.arg(0).asIntegerVector().findFirst().notNA(1); - testPipeline(); + arg.asIntegerVector().findFirst().notNA(1); + assertCastPreserves(42); assertEquals(1, cast(RRuntime.INT_NA)); + testPipeline(); } @Test public void testNoDoubleNA() { - cb.arg(0).asDoubleVector().findFirst().notNA(1.1); - testPipeline(); + arg.asDoubleVector().findFirst().notNA(1.1); + assertCastPreserves(3.142); assertEquals(1.1, cast(RRuntime.DOUBLE_NA)); + testPipeline(); } @Test public void testNoStringNA() { - cb.arg(0).asStringVector().findFirst().notNA("A"); - testPipeline(); + arg.asStringVector().findFirst().notNA("A"); + assertCastPreserves("hello world"); assertEquals("A", cast(RRuntime.DOUBLE_NA)); - } - - public InitialPhaseBuilder<String> matchStringArg(InitialPhaseBuilder<Object> phaseBuilder, String... optValues) { - ArgumentValueFilter<String> opts = null; - for (String opt : optValues) { - opts = opts == null ? equalTo(opt) : opts.or(equalTo(opt)); - } - return phaseBuilder.mustBe(scalarStringValue().and(opts)); - } - - @Test - public void testMatchArg() { - - cb.arg(0, "foo").mustBe(nullValue().or(scalarStringValue().and(equalTo("a").or(equalTo("b").or(equalTo("c"))))), RError.Message.GENERIC, "Invalid option").mapIf(nullValue(), constant("a")); - - cb.arg(0, "foo").alias(pb -> matchStringArg(pb, "a", "b", "c")).mapIf(equalTo("c"), constant("sss")); - - assertEquals("a", cast("a")); - assertEquals("b", cast("b")); - assertEquals("sss", cast("c")); - assertEquals("a", cast(RNull.instance)); - - try { - cast("d"); - fail(); - } catch (IllegalArgumentException e) { - // ok - } - } - - @Test - public void testSample0() { - cb.arg(0, "x").asIntegerVector().shouldBe(singleElement()).findFirst(0); testPipeline(); - - assertEquals(1, cast(RDataFactory.createIntVector(new int[]{1, 2}, true))); - // assertEquals(String.format(RError.Message.INVALID_ARGUMENT.message, "x"), - // out.toString()); } @Test - public void testSample1() { - cb.arg(0).asIntegerVector().mustBe(notEmpty(), RError.Message.LENGTH_ZERO); + public void testSingleElementWarning() { + arg.asIntegerVector().shouldBe(singleElement()).findFirst(0); + assertEquals(1, cast(RDataFactory.createIntVector(new int[]{1, 2}, true))); testPipeline(); - - try { - cast(RDataFactory.createIntVector(0)); - } catch (IllegalArgumentException e) { - assertEquals(RError.Message.LENGTH_ZERO.message, e.getMessage()); - } } @Test - public void testSample2() { - cb.arg(0).asIntegerVector().shouldBe(singleElement(), RError.Message.INVALID_USE, 1).mustBe(notEmpty(), RError.Message.ARGUMENT_EMPTY, 1); - testPipeline(); + public void testSingleElementWarningAndEmptyError() { + arg.asIntegerVector().shouldBe(singleElement(), RError.Message.INVALID_USE, "y").mustBe(notEmpty(), RError.Message.ARGUMENT_EMPTY, 42); - cast(RDataFactory.createIntVector(new int[]{1, 2}, true)); - // assertEquals(String.format(RError.Message.INVALID_USE.message, 1), out.toString()); - - try { - cast(RDataFactory.createIntVector(0)); - } catch (IllegalArgumentException e) { - assertEquals(String.format(RError.Message.ARGUMENT_EMPTY.message, 1), e.getMessage()); - } + RIntVector vec = RDataFactory.createIntVector(new int[]{1, 2}, true); + assertCastWarning(vec, vec, String.format(RError.Message.INVALID_USE.message, "y")); + assertCastFail(RDataFactory.createIntVector(0), String.format(Message.ARGUMENT_EMPTY.message, 42)); + testPipeline(); } @Test - public void testSample3() { - cb.arg(0).asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); - testPipeline(); - + public void testLogicalToBooleanPipeline() { + arg.asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); 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); } @Test - public void testSample4() { - // the predicate is attached to the error message - cb.arg(0).mustBe(ValuePredicateArgumentFilterSampler.fromLambdaWithResTypes(x -> x instanceof RAbstractIntVector || x instanceof Integer, Object.class), - Message.SEED_NOT_VALID_INT).asIntegerVector(); + public void testMustBeIntegerAndAsIntegerVector() { + arg.mustBe(integerValue(), Message.SEED_NOT_VALID_INT).asIntegerVector(); + assertCastPreserves(RDataFactory.createIntVector(new int[]{1, 2}, true)); + assertCastFail("x", RError.Message.SEED_NOT_VALID_INT.message); testPipeline(); - - cast(RDataFactory.createIntVector(new int[]{1, 2}, true)); - - try { - cast("x"); - } catch (IllegalArgumentException e) { - assertEquals(RError.Message.SEED_NOT_VALID_INT.message, e.getMessage()); - } } + //@formatter:off + @Test - public void testSample5() { - ArgumentTypeFilter<Object, Object> complexOrExpr = integerValue().or(doubleValue()).or(complexValue()).or(logicalValue()); - Assert.assertTrue(complexOrExpr instanceof ArgumentFilterSampler); - cb.arg(0).defaultError(RError.Message.INVALID_ARGUMENT, "fill").mustBe(numericValue().or(logicalValue())).asVector().mustBe(singleElement()).findFirst().shouldBe( - ValuePredicateArgumentFilterSampler.fromLambdaWithResTypes(x -> x instanceof Byte || x instanceof Integer && ((Integer) x) > 0), Message.NON_POSITIVE_FILL).mapIf( - scalarLogicalValue(), toBoolean()); - testPipeline(); + public void testComplexPipeline() { + arg.defaultError(RError.Message.INVALID_ARGUMENT, "fill"). + mustBe(numericValue().or(logicalValue())). + asVector().mustBe(singleElement()).findFirst(). + shouldBe(atomicLogicalValue().or(atomicIntegerValue().and(gt(0))), Message.NON_POSITIVE_FILL). + mapIf(atomicLogicalValue(), toBoolean()); + + assertCastPreserves(10); assertEquals(true, cast(RRuntime.LOGICAL_TRUE)); - assertEquals(10, cast(10)); - try { - cast("xyz"); - fail(); - } catch (IllegalArgumentException e) { - assertEquals(String.format(RError.Message.INVALID_ARGUMENT.message, "fill"), e.getMessage()); - } - try { - cast(RDataFactory.createIntVector(new int[]{1, 2}, true)); - fail(); - } catch (IllegalArgumentException e) { - assertEquals(String.format(RError.Message.INVALID_ARGUMENT.message, "fill"), e.getMessage()); - } - try { - cast(RDataFactory.createIntVector(0)); - fail(); - } catch (IllegalArgumentException e) { - assertEquals(String.format(RError.Message.INVALID_ARGUMENT.message, "fill"), e.getMessage()); - } - cast(-10); // warning - // assertEquals(String.format(Message.NON_POSITIVE_FILL.message, "fill"), out.toString()); + assertCastFail("xyz", String.format(RError.Message.INVALID_ARGUMENT.message, "fill")); + assertCastFail(RDataFactory.createIntVector(new int[]{1, 2}, true), String.format(RError.Message.INVALID_ARGUMENT.message, "fill")); + assertCastFail(RDataFactory.createIntVector(0), String.format(RError.Message.INVALID_ARGUMENT.message, "fill")); + assertCastWarning(-10, -10, String.format(Message.NON_POSITIVE_FILL.message, "fill")); + testPipeline(); } @Test - public void testSample6() { - cb.arg(0).map(defaultValue(RDataFactory.createStringVector(0))).mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "labels").asStringVector(); + public void testMapNull() { + arg.mapNull(emptyStringVector()).mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "labels").asStringVector(); testPipeline(); - assertEquals("abc", cast("abc")); + assertCastPreserves("abc", RDataFactory.createStringVector(new String[]{"abc", "def"}, true)); Object asv = cast(RNull.instance); assertEquals(true, asv instanceof RAbstractStringVector); assertEquals(0, ((RAbstractStringVector) asv).getLength()); - RAbstractStringVector sv = RDataFactory.createStringVector(new String[]{"abc", "def"}, true); - assertEquals(sv, cast(sv)); - - sv = RDataFactory.createStringVector(0); - asv = cast(sv); + asv = cast(RDataFactory.createStringVector(0)); assertEquals(true, asv instanceof RAbstractStringVector); assertEquals(0, ((RAbstractStringVector) asv).getLength()); - try { - cast(123); - } catch (IllegalArgumentException e) { - assertEquals(String.format(RError.Message.INVALID_ARGUMENT.message, "labels"), e.getMessage()); - } - - try { - cast(RNull.instance); - } catch (IllegalArgumentException e) { - assertEquals(String.format(RError.Message.INVALID_ARGUMENT.message, "labels"), e.getMessage()); - } + assertCastFail(123, String.format(RError.Message.INVALID_ARGUMENT.message, "labels")); } @Test - public void testSample7() { - cb.arg(0, "justify").asIntegerVector().findFirst().mustBe(gte(2).and(lte(5)).not()); - - testPipeline(true); - + public void testNumberComparison() { + arg.asIntegerVector().findFirst().mustBe(gte(2).and(lte(5)).not()); + assertCastPreserves(10, 0); + assertCastFail(2); + assertCastFail(5); + assertCastFail(3); + // TODO sampler does not work here testPipeline(NO_FILTER_EXPECT_EMPTY_SAMPLES); } @Test - public void testSample8() { - cb.arg(0, "blocking").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).map(toBoolean()).mustBe(trueValue(), RError.Message.NYI, "non-blocking mode not supported"); - cast(RNull.instance); - } - - @Test - public void testSample9() { - cb.arg(0, "arg").mapIf(instanceOf(RList.class).not(), nullConstant()); - - RList list = RDataFactory.createList(); - assertEquals(list, cast(list)); + public void testMapNonListToNull() { + arg.mapIf(instanceOf(RList.class).not(), nullConstant()); + assertCastPreserves(RDataFactory.createList()); assertEquals(RNull.instance, cast("abc")); } @Test - public void testSample10() { - cb.arg(0, "arg").mapIf(instanceOf(RList.class), nullConstant()); - - RList list = RDataFactory.createList(); - assertEquals(RNull.instance, cast(list)); - assertEquals("abc", cast("abc")); - } - - //@formatter:off - @Test - public void testSample11() { - cb.arg(0, "arg"). + public void testChain() { + arg. mapIf(instanceOf(RList.class).not(), chain(asLogicalVector()). with(findFirst().logicalElement()). with(notNA()). with(map(toBoolean())). - with(mustBe(instanceOf(Boolean.class), false)). - with(shouldBe(instanceOf(Object.class), false)). + with(mustBe(instanceOf(Boolean.class))). + with(shouldBe(instanceOf(Object.class))). end()); - RList list = RDataFactory.createList(); - assertEquals(list, cast(list)); + assertCastPreserves(RDataFactory.createList()); assertEquals(true, cast(1)); - try { - cast(RRuntime.INT_NA); - fail(); - } catch (IllegalArgumentException e) { - // ok - } + assertCastFail(RRuntime.INT_NA); } public Function<InitialPhaseBuilder<Object>, InitialPhaseBuilder<Object>> nonListToBoolean() { @@ -587,108 +486,198 @@ public class CastBuilderTest { } @Test - public void testSample12() { - cb.arg(0, "arg").alias(nonListToBoolean()); - - RList list = RDataFactory.createList(); - assertEquals(list, cast(list)); + public void testAlias() { + arg.alias(nonListToBoolean()); + assertCastPreserves(RDataFactory.createList()); assertEquals(true, cast(1)); } + //@formatter:on + @Test - public void testSample13() { - cb.arg(0, "arg").mapIf(numericValue(), BoxPrimitiveNodeGen.create()); + public void testAllowNullFindFirst() { + // Note: when null is allowed findFirst does not fail + arg.allowNull().mustBe(stringValue()).asStringVector().findFirst(); - Object res = cast(1); - Assert.assertTrue(res instanceof RInteger); - res = cast(RRuntime.LOGICAL_TRUE); - Assert.assertTrue(res instanceof RLogical); + assertCastPreserves("abc", RNull.instance); + assertEquals("abc", cast(RDataFactory.createStringVector(new String[]{"abc", "xyz"}, true))); + assertCastFail(RMissing.instance); } - //@formatter:on @Test - public void testSample14() { - cb.arg(0, "arg").mustBe(stringValue().or(nullValue())).mapIf(stringValue(), chain(asStringVector()).with(findFirst().stringElement()).end()); + public void notFirstNAElementInStringVector() { + arg.asStringVector().mustBe(elementAt(0, RRuntime.STRING_NA).not().and(singleElement())); - assertEquals("abc", cast("abc")); - assertEquals("abc", cast(RDataFactory.createStringVector(new String[]{"abc", "xyz"}, true))); - assertEquals(RNull.instance, cast(RNull.instance)); + assertCastPreserves(RDataFactory.createStringVector(new String[]{"abc"}, true), "abc"); + assertCastFail(RDataFactory.createStringVector(new String[]{"abc", "xyz"}, true)); + assertCastFail(RDataFactory.createStringVector(new String[]{RRuntime.STRING_NA}, false)); } @Test - public void testSample15() { - // cb.arg(0, "dim").asIntegerVector().mustBe(Predef.notEmpty()); + public void testMessageArgumentAsLambda() { + Function<Object, Object> argMsg = name -> "something"; + arg.conf(c -> c.allowNull().mustNotBeMissing(SHOW_CALLER, RError.Message.GENERIC, argMsg)).mustBe(stringValue(), RError.Message.GENERIC, argMsg); - cb.arg(0, "open").mustBe(instanceOf(RAbstractStringVector.class).and(singleElement()).and(elementAt(0, RRuntime.STRING_NA).not())); + assertCastPreserves(RNull.instance); + assertCastFail(RMissing.instance, "something"); + assertCastFail(42, "something"); + } - cast(RDataFactory.createStringVector(new String[]{"abc"}, true)); - try { - cast(RDataFactory.createStringVector(new String[]{"abc", "xyz"}, true)); - } catch (IllegalArgumentException e) { - // ok - } - try { - cast(RRuntime.STRING_NA); - } catch (IllegalArgumentException e) { - // ok - } + @Test + public void testSample17() { + // TODO: Filter implementation for sampling fails on assertion + arg.asDoubleVector().findFirst().mapIf(doubleNA().not().and(not(isFractional())), doubleToInt()); + + Object r = cast(RRuntime.STRING_NA); + assertTrue(r instanceof Double); + assertTrue(RRuntime.isNA((double) r)); + assertEquals(42, cast("42")); + assertEquals(42.2, cast("42.2")); + } + + @Test + public void testMustBeSquareMatrix() { + arg.asDoubleVector(true, true, true).mustBe(squareMatrix()); + + RIntVector vec = RDataFactory.createIntVector(new int[]{0, 1, 2, 3}, true, new int[]{2, 2}); + Object res = cast(vec); + assertTrue(res instanceof RAbstractDoubleVector); + RAbstractDoubleVector dvec = (RAbstractDoubleVector) res; + assertNotNull(dvec.getDimensions()); + assertEquals(2, dvec.getDimensions().length); + assertEquals(2, dvec.getDimensions()[0]); + assertEquals(2, dvec.getDimensions()[1]); + + RIntVector notSquare = RDataFactory.createIntVector(new int[]{0, 1, 2, 3}, true, new int[]{1, 4}); + assertCastFail(notSquare); } - private String argType(Object arg) { - return arg.getClass().getSimpleName(); + @Test + public void testDimensionsFilter() { + arg.asDoubleVector(true, true, true).mustBe(dimGt(1, 0)); + + RIntVector vec = RDataFactory.createIntVector(new int[]{0, 1, 2, 3}, true, new int[]{2, 2}); + RDoubleVector doubleVec = RDataFactory.createDoubleVector(new double[]{0, 1, 2, 3}, true, new int[]{2, 2}); + assertVectorEquals(doubleVec, cast(vec)); } - private String argMsg(Object arg) { - return "'data' must be of a vector type, was " + argType(arg); + @Test + public void testDimensionsFilterNegative() { + arg.asDoubleVector(true, true, true).mustBe(dimGt(4, 0)); + assertCastFail(RDataFactory.createIntVector(new int[]{0, 1, 2, 3}, true, new int[]{2, 2})); } @Test - public void testSample16() { - // cb.arg(0, "dim").asIntegerVector().mustBe(Predef.notEmpty()); - Function<Object, Object> argMsg = this::argMsg; - cb.arg(0, "open").shouldBe(stringValue(), RError.Message.GENERIC, argMsg); + public void testMapIf() { + arg.allowNull().mapIf(Predef.integerValue(), asIntegerVector(), asStringVector(true, false, false)); - cast(RNull.instance); + RDoubleVector vec = RDataFactory.createDoubleVector(new double[]{0, 1, 2, 3}, true); + Object res = cast(vec); + assertTrue(res instanceof RAbstractStringVector); + + assertCastPreserves(RDataFactory.createSharedIntVectorFromScalar(42)); } - class RBuiltinRootNode extends RootNode { + @Test + public void testSample21() { + arg.mustBe(numericValue()).asVector().mustBe(singleElement()).findFirst().shouldBe( + instanceOf(Byte.class).or(instanceOf(Integer.class).and(gt0())), + Message.NON_POSITIVE_FILL).mapIf(atomicLogicalValue(), asBoolean(), asInteger()); + // TODO: asserts + testPipeline(); + } - @Child private RBuiltinNode builtinNode; + @Test + public void testPreserveNonVectorFlag() { + arg.allowNull().asVector(true); + assertEquals(RNull.instance, cast(RNull.instance)); + } - RBuiltinRootNode(RBuiltinNode builtinNode) { - super(TruffleLanguage.class, null, null); - this.builtinNode = builtinNode; - } + @Test + public void testNotPreserveNonVectorFlag() { + arg.asVector(false); - @Override - public Object execute(VirtualFrame frame) { - return builtinNode.execute(frame); - } + Object res = cast(RNull.instance); + Assert.assertTrue(res instanceof RList); + Assert.assertEquals(0, ((RList) res).getLength()); } - private Object cast(Object arg) { + @Test + public void defaultErrorForMustNotBeNull() { + arg.defaultError(RError.SHOW_CALLER, Message.SEED_NOT_VALID_INT).mustNotBeNull(); + assertCastFail(RNull.instance, Message.SEED_NOT_VALID_INT.message); + } + + /** + * Casts given object using the configured pipeline in {@link #arg}. + */ + private Object cast(Object a) { CastNode argCastNode = cb.getCasts()[0]; NodeHandle<CastNode> argCastNodeHandle = TestUtilities.createHandle(argCastNode, (node, args) -> node.execute(args[0])); - return argCastNodeHandle.call(arg); + return argCastNodeHandle.call(a); + } + + private void assertCastPreserves(Object... values) { + for (Object value : values) { + assertCastPreserves(value); + } + } + + private void assertCastPreserves(Object value) { + assertEquals(value, cast(value)); + } + + private static void assertVectorEquals(RAbstractVector expected, Object actualObj) { + RAbstractVector actual = (RAbstractVector) actualObj; + assertEquals("vectors differ in size", expected.getLength(), actual.getLength()); + for (int i = 0; i < expected.getLength(); i++) { + assertEquals("vectors differ at position " + i, expected.getDataAtAsObject(i), actual.getDataAtAsObject(i)); + } + } + + private void assertCastWarning(Object value, Object expectedValue, String expectedMessage) { + assertEquals(expectedValue, cast(value)); + assertEquals("Expected warning message", expectedMessage, CastNode.getLastWarning()); + } + + private void assertCastFail(Object value) { + assertCastFail(value, String.format(RError.Message.INVALID_ARGUMENT.message, "x")); } + private void assertCastFail(Object value, String expectedMessage) { + try { + cast(value); + fail("cast should have failed"); + } catch (IllegalArgumentException e) { + assertEquals(expectedMessage, e.getMessage()); + } + } + + /** + * This tests the pipeline sampling process: all positive samples ase successful and all + * negative cause an error. + */ private void testPipeline() { - testPipeline(true); + testPipeline(false); } - private void testPipeline(@SuppressWarnings("unused") boolean positiveMustNotBeEmpty) { + private void testPipeline(boolean emptyPositiveSamplesAllowed) { + if (!TEST_SAMPLING) { + return; + } + CastNodeSampler<CastNode> sampler = CastNodeSampler.createSampler(cb.getCasts()[0]); Samples<?> samples = sampler.collectSamples(); - // - // if (positiveMustNotBeEmpty) { - // Assert.assertFalse(samples.positiveSamples().isEmpty()); - // } - // - // testPipeline(samples); + if (!emptyPositiveSamplesAllowed) { + Assert.assertFalse(samples.positiveSamples().isEmpty()); + } + testPipeline(samples); } - @SuppressWarnings("unused") private void testPipeline(Samples<?> samples) { + if (!TEST_SAMPLING) { + return; + } for (Object sample : samples.positiveSamples()) { try { @@ -707,4 +696,11 @@ 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 { + } } 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/builtin/TypeExprTest.java index 02278b9ec81b0b2ce66cb16288b9b9bc35193881..c417e4e73e0165eab37e86ab64a1c90d9045e2bf 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/builtin/TypeExprTest.java @@ -34,7 +34,10 @@ import java.util.Set; import org.junit.Assert; 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.runtime.data.RIntSequence; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RSequence; @@ -55,6 +58,22 @@ public class TypeExprTest { Assert.assertEquals(toSet(TypeConjunction.create(RAbstractIntVector.class, RAbstractStringVector.class)), atom(RAbstractIntVector.class).and(atom(RAbstractStringVector.class)).normalize()); } + @Test + public void testContains() { + TypeExpr te = atom(String.class).or(atom(RNull.class).not()); + Assert.assertTrue(te.contains(String.class)); + Assert.assertTrue(te.contains(Not.negateType(RNull.class))); + Assert.assertFalse(te.contains(RNull.class)); + } + + @Test + public void testNot() { + TypeExpr from = atom(String.class).or(atom(RNull.class).not()); + Assert.assertFalse(CastUtils.Casts.existsConvertibleActualType(from, RNull.class, false)); + Assert.assertTrue(CastUtils.Casts.existsConvertibleActualType(from, String.class, false)); + Assert.assertTrue(CastUtils.Casts.existsConvertibleActualType(from, Integer.class, false)); + } + 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/builtin/base/printer/ComplexVectorPrinterTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f95c7b59a40636b8746370280ca2a8a9c6c441a2 --- /dev/null +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinterTest.java @@ -0,0 +1,38 @@ +/* + * 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.builtin.base.printer; + +import org.junit.Test; + +import com.oracle.truffle.r.runtime.data.RDataFactory; + +import static org.junit.Assert.*; + +public class ComplexVectorPrinterTest { + + @Test + public void testEncodeComplex() { + assertEquals("3.14159265358979e-05+3.1415926535898e-06i", ComplexVectorPrinter.encodeComplex(RDataFactory.createComplex(Math.PI / 100000, Math.PI / 1000000))); + } + +} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinterTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4dcf54e8d8e3539e7734cc94ac10627e23c33c19 --- /dev/null +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinterTest.java @@ -0,0 +1,36 @@ +/* + * 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.builtin.base.printer; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class DoubleVectorPrinterTest { + + @Test + public void testEncodeReal() { + assertEquals("3.14159265358979e-06", DoubleVectorPrinter.encodeReal(Math.PI / 1000000)); + } + +} 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 index d3a51f559e4c4b4365265c7e451f1cda91118265..979813ce02f49487c5fb8184e851ffc1c7fa4bc7 100644 --- 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 @@ -232,7 +232,6 @@ public interface ArgumentFilterSampler<T, R> extends ArgumentFilter<T, R> { return ArgumentTypeFilterSampler.this.trueBranchType().and(other.trueBranchType()); } - @SuppressWarnings("cast") @Override public Samples<R> collectSamples(TypeExpr inputType) { Samples<R> thisSamples = ArgumentTypeFilterSampler.this.collectSamples(inputType); @@ -269,7 +268,6 @@ public interface ArgumentFilterSampler<T, R> extends ArgumentFilter<T, R> { return orig.falseBranchType().not(); } - @SuppressWarnings("unchecked") @Override public Samples<Object> collectSamples(TypeExpr inputType) { Samples<? extends R> thisSamples = orig.collectSamples(inputType); 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 index f90d1ec73c701252e434c56b4e9a4e3e4b6703dd..0e64e2c2cd775661cf03bad5498dce8dcaecad4a 100644 --- 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 @@ -23,11 +23,6 @@ package com.oracle.truffle.r.nodes.casts; import java.lang.reflect.Constructor; -import java.lang.reflect.Type; -import java.util.Collections; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; import com.oracle.truffle.r.nodes.unary.CastNode; 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 9981b36e9248af9aa982861c06f101a588f6aef0..43aa139fef2f0ab669fbe85567b1a3e135320956 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 @@ -52,8 +52,6 @@ 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 sun.java2d.xr.XRCompositeManager; - public class CastUtils { public static final class Cast { @@ -672,6 +670,10 @@ public class CastUtils { return te.normalize().stream().flatMap(t -> CastUtils.sampleValuesForType(t).stream()).collect(Collectors.toSet()); } + public static Set<?> sampleValuesForClases(Class<?>[] classes) { + return Arrays.stream(classes).flatMap(t -> CastUtils.sampleValuesForType(t).stream()).collect(Collectors.toSet()); + } + public static Set<?> sampleValuesForType(Type t) { HashSet<Object> samples = new HashSet<>(); @@ -787,21 +789,20 @@ public class CastUtils { @SuppressWarnings("varargs") @SafeVarargs - public static <T> Set<? extends T> samples(T samplesHead, T... samplesTail) { + public static <T> Set<T> samples(T samplesHead, T... samplesTail) { HashSet<T> sampleSet = new HashSet<>(Arrays.asList(samplesTail)); sampleSet.add(samplesHead); return sampleSet; } - @SuppressWarnings("unchecked") - public static <T> Set<? extends T> samples(T s) { + public static <T> Set<T> samples(T s) { if (s == null) { - return Collections.singleton((T) RNull.instance); + return Collections.emptySet(); } return Collections.singleton(s); } - public static <T> Set<? extends T> samples() { + public static <T> Set<T> samples() { return Collections.emptySet(); } 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 new file mode 100644 index 0000000000000000000000000000000000000000..bc27e20cff7fa53c0d6879e514addaf5f39b55bd --- /dev/null +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/FilterSamplerFactory.java @@ -0,0 +1,468 @@ +/* + * 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 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.NotFilter; +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); + } + + @Override + public ArgumentFilterSampler<?, ?> visit(TypeFilter<?, ?> filter) { + return TypePredicateArgumentFilterSampler.fromLambda(toPredicate(filter.getInstanceOfLambda()), + CastUtils.sampleValuesForClases(filter.getType()), CastUtils.samples(null), filter.getType()); + } + + @Override + public ArgumentFilterSampler<?, ?> visit(RTypeFilter<?> filter) { + if (filter.getType() == RType.Integer) { + return visit(new TypeFilter<>(x -> x instanceof Integer || x instanceof RAbstractIntVector, Integer.class, RAbstractIntVector.class)); + } else if (filter.getType() == RType.Double) { + return visit(new TypeFilter<>(x -> x instanceof Double || x instanceof RAbstractDoubleVector, Double.class, RAbstractDoubleVector.class)); + } else if (filter.getType() == RType.Logical) { + return visit(new TypeFilter<>(x -> x instanceof Byte || x instanceof RAbstractLogicalVector, Byte.class, RAbstractLogicalVector.class)); + } else if (filter.getType() == RType.Complex) { + return visit(new TypeFilter<>(x -> x instanceof RAbstractComplexVector, RAbstractComplexVector.class)); + } else if (filter.getType() == RType.Character) { + return visit(new TypeFilter<>(x -> x instanceof String || x instanceof RAbstractStringVector, String.class, RAbstractStringVector.class)); + } else if (filter.getType() == RType.Raw) { + return visit(new TypeFilter<>(x -> x instanceof RAbstractRawVector, 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", "cast"}) + @Override + public Samples<Object> collectSamples(TypeExpr inputType) { + Samples thisSamples = toNegate.collectSamples(inputType); + return (Samples<Object>) thisSamples.swap(); + } + + }; + } + + @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 new file mode 100644 index 0000000000000000000000000000000000000000..078025424b81a925c04df8a7daa619afc9312be9 --- /dev/null +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MapperSamplerFactory.java @@ -0,0 +1,95 @@ +/* + * 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/PredefFiltersSamplers.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/PredefFiltersSamplers.java deleted file mode 100644 index 19994502bba6cd768faea9f7f04a4583419c3295..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/PredefFiltersSamplers.java +++ /dev/null @@ -1,292 +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 static com.oracle.truffle.r.nodes.casts.CastUtils.samples; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Objects; - -import com.oracle.truffle.r.nodes.builtin.CastBuilder.PredefFilters; -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.RMissing; -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.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; - -public final class PredefFiltersSamplers implements PredefFilters { - - @Override - public <T> ValuePredicateArgumentFilterSampler<T> sameAs(T x) { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples(arg -> arg == x, samples(x), CastUtils.<T> samples()); - } - - @Override - public <T> ValuePredicateArgumentFilterSampler<T> equalTo(T x) { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples(arg -> Objects.equals(arg, x), samples(x), CastUtils.<T> samples()); - } - - @Override - public <T, R extends T> TypePredicateArgumentFilterSampler<T, R> nullValue() { - // return TypePredicateArgumentFilterSampler.fromLambda(x -> x == RNull.instance || x == - // null, CastUtils.<R> samples(null), CastUtils.<R> samples(), RNull.class); - return new TypePredicateArgumentFilterSampler<>("nullValue()", x -> x == RNull.instance || x == null, CastUtils.<R> samples(null), CastUtils.<R> samples(), Collections.singleton(RNull.class), - true); - } - - @Override - public <T extends RAbstractVector> VectorPredicateArgumentFilterSampler<T> notEmpty() { - return new VectorPredicateArgumentFilterSampler<>("notEmpty()", x -> x.getLength() > 0, false, 0); - } - - @Override - public <T extends RAbstractVector> VectorPredicateArgumentFilterSampler<T> singleElement() { - return new VectorPredicateArgumentFilterSampler<>("singleElement()", x -> { - return x.getLength() == 1; - }, false, 0, 2); - } - - @Override - public VectorPredicateArgumentFilterSampler<RAbstractStringVector> elementAt(int index, String value) { - return new VectorPredicateArgumentFilterSampler<>("elementAt", x -> index < x.getLength() && value.equals(x.getDataAtAsObject(index)), false, 0, index); - } - - @Override - public VectorPredicateArgumentFilterSampler<RAbstractIntVector> elementAt(int index, int value) { - return new VectorPredicateArgumentFilterSampler<>("elementAt", x -> index < x.getLength() && value == (int) (x.getDataAtAsObject(index)), false, 0, index); - } - - @Override - public VectorPredicateArgumentFilterSampler<RAbstractDoubleVector> elementAt(int index, double value) { - return new VectorPredicateArgumentFilterSampler<>("elementAt", x -> index < x.getLength() && value == (double) (x.getDataAtAsObject(index)), false, 0, index); - } - - @Override - public VectorPredicateArgumentFilterSampler<RAbstractComplexVector> elementAt(int index, RComplex value) { - return new VectorPredicateArgumentFilterSampler<>("elementAt", x -> index < x.getLength() && value.equals(x.getDataAtAsObject(index)), false, 0, index); - } - - @Override - public VectorPredicateArgumentFilterSampler<RAbstractLogicalVector> elementAt(int index, byte value) { - return new VectorPredicateArgumentFilterSampler<>("elementAt", x -> index < x.getLength() && value == (byte) (x.getDataAtAsObject(index)), false, 0, index); - } - - @Override - public <T extends RAbstractVector, R extends T> VectorPredicateArgumentFilterSampler<T> size(int s) { - if (s == 0) { - return new VectorPredicateArgumentFilterSampler<>("size(int)", x -> x.getLength() == s, false, s - 1, s + 1); - } else { - return new VectorPredicateArgumentFilterSampler<>("size(int)", x -> x.getLength() == s, false, 0, s - 1, s + 1); - } - } - - @Override - public ValuePredicateArgumentFilterSampler<Boolean> trueValue() { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples(x -> x, samples(Boolean.TRUE), samples(Boolean.FALSE)); - } - - @Override - public ValuePredicateArgumentFilterSampler<Boolean> falseValue() { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples(x -> x, samples(Boolean.FALSE), samples(Boolean.TRUE)); - } - - @Override - public ValuePredicateArgumentFilterSampler<Byte> logicalTrue() { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples(x -> RRuntime.LOGICAL_TRUE == x, samples(RRuntime.LOGICAL_TRUE), - samples(RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA)); - } - - @Override - public ValuePredicateArgumentFilterSampler<Byte> logicalFalse() { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples(x -> RRuntime.LOGICAL_FALSE == x, samples(RRuntime.LOGICAL_FALSE), - samples(RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_NA)); - } - - @Override - public ValuePredicateArgumentFilterSampler<Integer> intNA() { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer x) -> RRuntime.isNA(x), samples(RRuntime.INT_NA), samples(0)); - } - - @Override - public ValuePredicateArgumentFilterSampler<Byte> logicalNA() { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Byte x) -> RRuntime.isNA(x), samples(RRuntime.LOGICAL_NA), - samples(RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE)); - } - - @Override - public ValuePredicateArgumentFilterSampler<Double> doubleNA() { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double x) -> RRuntime.isNA(x), samples(RRuntime.DOUBLE_NA), samples(0d)); - } - - @Override - public ValuePredicateArgumentFilterSampler<String> stringNA() { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String x) -> RRuntime.isNA(x), samples(RRuntime.STRING_NA), samples("")); - } - - @Override - public ValuePredicateArgumentFilterSampler<Integer> eq(int x) { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer arg) -> arg != null && arg.intValue() == x, samples(x), CastUtils.<Integer> samples(x + 1)); - } - - @Override - public ValuePredicateArgumentFilterSampler<Double> eq(double x) { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double arg) -> arg != null && arg.doubleValue() == x, samples(x), CastUtils.<Double> samples(x + 1)); - } - - @Override - public ValuePredicateArgumentFilterSampler<Integer> gt(int x) { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer arg) -> arg != null && arg > x, samples(x + 1), samples(x)); - } - - @Override - public ValuePredicateArgumentFilterSampler<Double> gt(double x) { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double arg) -> arg != null && arg > x, CastUtils.<Double> samples(), samples(x)); - } - - @Override - public ValuePredicateArgumentFilterSampler<Double> gte(double x) { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double arg) -> arg != null && arg >= x, samples(x), samples(x - 1)); - } - - @Override - public ValuePredicateArgumentFilterSampler<Integer> lt(int x) { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer arg) -> arg != null && arg < x, samples(x - 1), samples(x)); - } - - @Override - public ValuePredicateArgumentFilterSampler<Double> lt(double x) { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double arg) -> arg < x, CastUtils.<Double> samples(), samples(x)); - } - - @Override - public ValuePredicateArgumentFilterSampler<Double> lte(double x) { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double arg) -> arg <= x, samples(x), samples(x + 1)); - } - - @Override - public ValuePredicateArgumentFilterSampler<String> length(int l) { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String arg) -> arg != null && arg.length() == l, samples(sampleString(l)), - samples(sampleString(l + 1))); - } - - @Override - public ValuePredicateArgumentFilterSampler<String> lengthGt(int l) { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String arg) -> arg != null && arg.length() > l, samples(sampleString(l + 1)), - samples(sampleString(l))); - } - - @Override - public ValuePredicateArgumentFilterSampler<String> lengthLt(int l) { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String arg) -> arg != null && arg.length() < l, samples(sampleString(l - 1)), - samples(sampleString(l))); - } - - @Override - public <R> TypePredicateArgumentFilterSampler<Object, R> instanceOf(Class<R> cls) { - return TypePredicateArgumentFilterSampler.fromLambda(x -> cls.isInstance(x), CastUtils.<R> samples(), samples(null), cls); - } - - @Override - public <R extends RAbstractIntVector> TypePredicateArgumentFilterSampler<Object, R> integerValue() { - return TypePredicateArgumentFilterSampler.fromLambda(x -> x instanceof Integer || x instanceof RAbstractIntVector, CastUtils.<R> samples(), CastUtils.<Object> samples(null), - RAbstractIntVector.class, - Integer.class); - } - - @Override - public <R extends RAbstractStringVector> TypePredicateArgumentFilterSampler<Object, R> stringValue() { - return TypePredicateArgumentFilterSampler.fromLambda(x -> x instanceof String || - x instanceof RAbstractStringVector, CastUtils.<R> samples(), CastUtils.<Object> samples(null), RAbstractStringVector.class, String.class); - } - - @Override - public <R extends RAbstractDoubleVector> TypePredicateArgumentFilterSampler<Object, R> doubleValue() { - return TypePredicateArgumentFilterSampler.fromLambda(x -> x instanceof Double || - x instanceof RAbstractDoubleVector, CastUtils.<R> samples(), CastUtils.<Object> samples(null), RAbstractDoubleVector.class, Double.class); - } - - @SuppressWarnings("unchecked") - @Override - public <R extends RAbstractLogicalVector> TypePredicateArgumentFilterSampler<Object, R> logicalValue() { - return TypePredicateArgumentFilterSampler.fromLambda(x -> x instanceof Byte || - x instanceof RAbstractLogicalVector, - samples((R) RDataFactory.createLogicalVectorFromScalar(RRuntime.LOGICAL_TRUE), (R) RDataFactory.createLogicalVectorFromScalar(RRuntime.LOGICAL_FALSE), - (R) RDataFactory.createLogicalVectorFromScalar(RRuntime.LOGICAL_NA)), - CastUtils.samples(null), RAbstractLogicalVector.class, - Byte.class); - } - - @Override - public <R extends RAbstractComplexVector> TypePredicateArgumentFilterSampler<Object, R> complexValue() { - return TypePredicateArgumentFilterSampler.fromLambda(x -> x instanceof RComplex || - x instanceof RAbstractComplexVector, RAbstractComplexVector.class, RComplex.class); - } - - @Override - public TypePredicateArgumentFilterSampler<Object, String> scalarStringValue() { - return TypePredicateArgumentFilterSampler.fromLambda(x -> x instanceof String, CastUtils.<String> samples(), CastUtils.<Object> samples(null), String.class); - } - - @Override - public TypePredicateArgumentFilterSampler<Object, Integer> scalarIntegerValue() { - return TypePredicateArgumentFilterSampler.fromLambda(x -> x instanceof Integer, CastUtils.<Integer> samples(), CastUtils.<Object> samples(null), Integer.class); - } - - @Override - public TypePredicateArgumentFilterSampler<Object, Double> scalarDoubleValue() { - return TypePredicateArgumentFilterSampler.fromLambda(x -> x instanceof Double, CastUtils.<Double> samples(), CastUtils.<Object> samples(null), Double.class); - } - - @Override - public TypePredicateArgumentFilterSampler<Object, Byte> scalarLogicalValue() { - return TypePredicateArgumentFilterSampler.fromLambda(x -> x instanceof Byte, samples(RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA), CastUtils.<Object> samples(null), - Byte.class); - } - - @Override - public TypePredicateArgumentFilterSampler<Object, RComplex> scalarComplexValue() { - return TypePredicateArgumentFilterSampler.fromLambda(x -> x instanceof RComplex, RComplex.class); - } - - @Override - public TypePredicateArgumentFilterSampler<Object, RMissing> missingValue() { - return TypePredicateArgumentFilterSampler.fromLambda(x -> RMissing.instance == x, RMissing.class); - } - - private static String sampleString(int len) { - if (len <= 0) { - return ""; - } else { - char[] ch = new char[len]; - Arrays.fill(ch, 'a'); - return String.valueOf(ch); - } - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/PredefMappersSamplers.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/PredefMappersSamplers.java deleted file mode 100644 index 81709b92c63611dbfa2fa8d0a77f26c63a19707c..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/PredefMappersSamplers.java +++ /dev/null @@ -1,120 +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 static com.oracle.truffle.r.nodes.casts.CastUtils.samples; - -import java.util.Collections; - -import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.nodes.builtin.CastBuilder.PredefMappers; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RNull; - -public final class PredefMappersSamplers implements PredefMappers { - - @Override - public ValuePredicateArgumentMapperSampler<Byte, Boolean> toBoolean() { - return ValuePredicateArgumentMapperSampler.fromLambda(x -> RRuntime.fromLogical(x), x -> RRuntime.asLogical(x), samples(RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA), - CastUtils.<Byte> samples(), Byte.class, Boolean.class); - } - - @Override - public ValuePredicateArgumentMapperSampler<String, Integer> charAt0(int defaultValue) { - 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 == RRuntime.INT_NA ? RRuntime.STRING_NA : "" + (char) x.intValue(); - } - }, samples(defaultValue == RRuntime.INT_NA ? RRuntime.STRING_NA : "" + (char) defaultValue), CastUtils.<String> samples(), String.class, Integer.class); - } - - @Override - public <T> ValuePredicateArgumentMapperSampler<T, RNull> nullConstant() { - return ValuePredicateArgumentMapperSampler.<T, RNull> fromLambda((T x) -> RNull.instance, null, null, RNull.class); - } - - @Override - public ValuePredicateArgumentMapperSampler<String, String> constant(String s) { - return ValuePredicateArgumentMapperSampler.<String, String> fromLambda((String x) -> s, (String x) -> s, CastUtils.<String> samples(), CastUtils.<String> samples(), String.class, - String.class); - } - - @Override - public ValuePredicateArgumentMapperSampler<Integer, Integer> constant(int i) { - return ValuePredicateArgumentMapperSampler.fromLambda(x -> i, x -> i, CastUtils.<Integer> samples(), CastUtils.<Integer> samples(), Integer.class, Integer.class); - } - - @Override - public ValuePredicateArgumentMapperSampler<Double, Double> constant(double d) { - return ValuePredicateArgumentMapperSampler.fromLambda(x -> d, x -> d, CastUtils.<Double> samples(), CastUtils.<Double> samples(), Double.class, Double.class); - } - - @Override - public ValuePredicateArgumentMapperSampler<Byte, Byte> constant(byte l) { - return ValuePredicateArgumentMapperSampler.fromLambda(x -> l, x -> l, CastUtils.<Byte> samples(), CastUtils.<Byte> samples(), Byte.class, Byte.class); - } - - @Override - public <T> ArgumentMapperSampler<T, T> defaultValue(T defVal) { - - assert (defVal != null); - - return new ArgumentMapperSampler<T, T>() { - - final ConditionProfile profile = ConditionProfile.createBinaryProfile(); - - @Override - public T map(T arg) { - if (profile.profile(arg == RNull.instance || arg == null)) { - return defVal; - } else { - return arg; - } - } - - @Override - public TypeExpr resultTypes(TypeExpr inputTypes) { - return inputTypes.and(TypeExpr.atom(RNull.class).not()); - } - - @SuppressWarnings("unchecked") - @Override - public Samples<T> collectSamples(Samples<T> downStreamSamples) { - Samples<Object> nullOnly = new Samples<>("RNullOnly", Collections.singleton(RNull.instance), Collections.emptySet(), x -> x == RNull.instance); - return (Samples<T>) nullOnly.or(Samples.anything(defVal).and(downStreamSamples)); - } - }; - } -} 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 e548800b848bc5c046f89e56cf59a3a0dd042cbf..3a65ebcc6d0c5373efe94d1f363de221d95fe278 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 @@ -33,6 +33,7 @@ import java.util.stream.Collectors; public final class Samples<T> { private static final Samples<?> ANYTHING = new Samples<>("anything", Collections.emptySet(), Collections.emptySet(), x -> true); + private static final Samples<?> NOTHING = new Samples<>("nothing", Collections.emptySet(), Collections.emptySet(), x -> false); @SuppressWarnings("unchecked") public static <T> Samples<T> anything() { @@ -43,6 +44,11 @@ public final class Samples<T> { return new Samples<>("anything(" + x + ")", Collections.singleton(x), Collections.emptySet(), xx -> true); } + @SuppressWarnings("unchecked") + public static <T> Samples<T> nothing() { + return (Samples<T>) NOTHING; + } + private final Set<? extends T> posSamples; private final Set<?> negSamples; private final Predicate<Object> posMembership; @@ -124,7 +130,7 @@ public final class Samples<T> { } @SuppressWarnings("unchecked") - public Samples<T> or(Samples<? extends T> other) { + public Samples<T> or(Samples<?> other) { String newName = "or(" + name + "," + other.name + ")"; Set<Object> negativeUnion = new HashSet<>(other.negativeSamples()); 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 05d7c3b1e78cd10130300c569de72aa7be04bf51..61a372bc9e838373c29cbbb31452048e4a6ef0ad 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 @@ -30,7 +30,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asLogicalVec import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asStringVector; 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.defaultValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt0; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; @@ -38,15 +37,11 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue 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.numericValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.scalarIntegerValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.scalarLogicalValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; -import java.io.IOException; -import java.io.OutputStream; +import java.util.function.Consumer; import org.junit.Test; @@ -138,12 +133,18 @@ public class TestCasts extends TestBase { } } + private static CastNode setupAndGetCast(Consumer<CastBuilder> setup) { + CastBuilder builder = new CastBuilder(1); + setup.accept(builder); + return builder.getCasts()[0]; + } + @Test public void testFirstIntegers() { class Root extends TestRootNode<CastNode> { protected Root(String name) { - super(name, new CastBuilder().firstIntegerWithError(0, Message.INVALID_ARGUMENT, "foo").getCasts()[0]); + super(name, setupAndGetCast(b -> b.arg(0, "foo").asIntegerVector().findFirst())); } @Override @@ -164,7 +165,7 @@ public class TestCasts extends TestBase { private final Object constant; protected Root(String name, Object constant) { - super(name, new CastBuilder().firstIntegerWithError(0, Message.INVALID_ARGUMENT, "foo").getCasts()[0]); + super(name, setupAndGetCast(b -> b.arg(0, "foo").asIntegerVector().findFirst())); this.constant = constant; } @@ -185,7 +186,7 @@ public class TestCasts extends TestBase { class Root extends TestRootNode<CastNode> { protected Root(String name) { - super(name, new CastBuilder().arg(0).mustBe(integerValue()).builder().getCasts()[0]); + super(name, setupAndGetCast(b -> b.arg(0).mustBe(integerValue()))); } @Override @@ -203,7 +204,7 @@ public class TestCasts extends TestBase { class Root extends TestRootNode<CastNode> { protected Root(String name) { - super(name, new CastBuilder().arg(0).map(defaultValue("X")).builder().getCasts()[0]); + super(name, setupAndGetCast(b -> b.arg(0).mapNull(constant("X")))); } @Override @@ -221,7 +222,7 @@ public class TestCasts extends TestBase { class Root extends TestRootNode<CastNode> { protected Root(String name) { - super(name, new CastBuilder().arg(0).mustBe(String.class).map(charAt0(0)).builder().getCasts()[0]); + super(name, setupAndGetCast(b -> b.arg(0).mustBe(String.class).map(charAt0(0)))); } @Override @@ -241,7 +242,7 @@ public class TestCasts extends TestBase { final boolean mustBeResultCompilationConstant; protected Root(String name, boolean mustBeResultCompilationConstant) { - super(name, new CastBuilder().arg(0).mapIf(scalarIntegerValue(), constant(10)).builder().getCasts()[0]); + super(name, setupAndGetCast(b -> b.arg(0).mapIf(instanceOf(Integer.class), constant(10)))); this.mustBeResultCompilationConstant = mustBeResultCompilationConstant; } @@ -265,7 +266,7 @@ public class TestCasts extends TestBase { private final Object constant; protected Root(String name, Object constant) { - super(name, new CastBuilder().arg(0).mustBe(integerValue()).builder().getCasts()[0]); + super(name, setupAndGetCast(b -> b.arg(0).mustBe(integerValue()))); this.constant = constant; } @@ -279,6 +280,27 @@ public class TestCasts extends TestBase { testCompilation(new Object[]{1}, new Root("MustBeWithConstant", 1)); } + @Test + public void optimizedBypass() { + class Root extends TestRootNode<CastNode> { + + private final Object constant; + + protected Root(String name, Object constant) { + super(name, setupAndGetCast(b -> b.arg(0).mustBe(integerValue()).asIntegerVector().findFirst())); + this.constant = constant; + } + + @Override + protected Object execute(VirtualFrame frame, Object value) { + int result = (int) node.execute(constant); + CompilerAsserts.compilationConstant(result); + return null; + } + } + testCompilation(new Object[]{1}, new Root("optimizeBypass1", 1)); + } + @Test public void testConditionalMapChainWithConstant() { class Root extends TestRootNode<CastNode> { @@ -286,8 +308,8 @@ public class TestCasts extends TestBase { private final Object constant; protected Root(String name, Object constant) { - super(name, new CastBuilder().arg(0).mapIf(stringValue(), asStringVector()).mapIf(integerValue(), asIntegerVector()).mapIf(logicalValue(), asLogicalVector(), - asDoubleVector()).builder().getCasts()[0]); + super(name, setupAndGetCast(b -> b.arg(0).mapIf(stringValue(), asStringVector()).mapIf(integerValue(), asIntegerVector()).mapIf(logicalValue(), asLogicalVector(), + asDoubleVector()))); this.constant = constant; } @@ -311,8 +333,8 @@ public class TestCasts extends TestBase { class Root extends TestRootNode<CastNode> { protected Root(String name) { - super(name, new CastBuilder().arg(0).mapIf(stringValue(), asStringVector()).mapIf(doubleValue(), asDoubleVector()).mapIf(logicalValue(), asLogicalVector(), - asIntegerVector()).builder().getCasts()[0]); + super(name, setupAndGetCast(b -> b.arg(0).mapIf(stringValue(), asStringVector()).mapIf(doubleValue(), asDoubleVector()).mapIf(logicalValue(), asLogicalVector(), + asIntegerVector()))); } @Override @@ -342,35 +364,13 @@ public class TestCasts extends TestBase { RDataFactory.createStringVectorFromScalar("abc")}, new Root("ConditionalMapChainFedByString2"), 1.1, 1, RRuntime.LOGICAL_FALSE); } - @Test - public void testComplexPipeline1() { - class Root extends TestRootNode<CastNode> { - - protected Root(String name) { - super(name, new CastBuilder().arg(0).mustBe(numericValue()).asVector().mustBe(singleElement()).findFirst().mustBe(nullValue().not()).shouldBe( - ValuePredicateArgumentFilterSampler.fromLambdaWithResTypes(x -> x instanceof Byte || x instanceof Integer && ((Integer) x) > 0, Object.class), - Message.NON_POSITIVE_FILL).mapIf(scalarLogicalValue(), asBoolean(), asInteger()).builder().getCasts()[0]); - } - - @Override - protected Object execute(VirtualFrame frame, Object value) { - @SuppressWarnings("unused") - Object res = node.execute(value); - return null; - } - } - testCompilation(new Object[]{RDataFactory.createIntVectorFromScalar(77)}, new Root("ComplexPipeline1Integer")); - testCompilation(new Object[]{RDataFactory.createIntVectorFromScalar(77), RDataFactory.createLogicalVectorFromScalar(RRuntime.LOGICAL_FALSE)}, new Root("ComplexPipeline1IntegerLogical")); - testCompilation(new Object[]{RDataFactory.createIntVectorFromScalar(77), RDataFactory.createDoubleVectorFromScalar(77.77)}, new Root("ComplexPipeline1IntegerDouble")); - } - @Test public void testComplexPipeline2() { class Root extends TestRootNode<CastNode> { protected Root(String name) { - super(name, new CastBuilder().arg(0).mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().mustBe(lengthLte(1)).map( - charAt0(RRuntime.INT_NA)).notNA(100000).builder().getCasts()[0]); + super(name, setupAndGetCast(b -> b.arg(0).mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().mustBe(lengthLte(1)).map( + charAt0(RRuntime.INT_NA)).notNA(100000))); } @Override @@ -389,7 +389,7 @@ public class TestCasts extends TestBase { class Root extends TestRootNode<CastNode> { protected Root(String name) { - super(name, new CastBuilder().arg(0).mustBe(stringValue().or(integerValue())).builder().getCasts()[0]); + super(name, setupAndGetCast(b -> b.arg(0).mustBe(stringValue().or(integerValue())))); } @Override @@ -408,7 +408,7 @@ public class TestCasts extends TestBase { class Root extends TestRootNode<CastNode> { protected Root(String name) { - super(name, new CastBuilder().arg(0).mustBe(scalarIntegerValue()).shouldBe(gt0().and(lt(10))).builder().getCasts()[0]); + super(name, setupAndGetCast(b -> b.arg(0).mustBe(instanceOf(Integer.class)).shouldBe(gt0().and(lt(10))))); } @Override @@ -426,7 +426,7 @@ public class TestCasts extends TestBase { class Root extends TestRootNode<CastNode> { protected Root(String name) { - super(name, new CastBuilder().arg(0).mustBe(scalarIntegerValue()).shouldBe(gt0().and(lt(10)).not()).builder().getCasts()[0]); + super(name, setupAndGetCast(b -> b.arg(0).mustBe(instanceOf(Integer.class)).shouldBe(gt0().and(lt(10)).not()))); } @Override @@ -444,9 +444,9 @@ public class TestCasts extends TestBase { class Root extends TestRootNode<CastNode> { protected Root(String name) { - super(name, new CastBuilder().arg(0).mustBe(numericValue()).asVector().mustBe(singleElement()).findFirst().mustBe(nullValue().not()).shouldBe( - instanceOf(Byte.class).or(instanceOf(Integer.class).and(gt0())), Message.NON_POSITIVE_FILL).mapIf(scalarLogicalValue(), asBoolean(), - asInteger()).builder().getCasts()[0]); + super(name, setupAndGetCast(b -> b.arg(0).mustBe(numericValue()).asVector().mustBe(singleElement()).findFirst().shouldBe( + instanceOf(Byte.class).or(instanceOf(Integer.class).and(gt0())), Message.NON_POSITIVE_FILL).mapIf(instanceOf(Byte.class), asBoolean(), + asInteger()))); } @Override 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 32ae7bcc5e976b28d118869730659d86db62a44a..a462d9311b4c998c8eb7295c7a2c7b486a12bab8 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 @@ -74,6 +74,10 @@ public final class TypeExpr { return new TypeExpr(newDisjNormForm); } + public boolean contains(Type tp) { + return disjNormForm.stream().flatMap(conjSet -> conjSet.stream().filter(t -> t.equals(tp))).findFirst().isPresent(); + } + public TypeExpr or(TypeExpr te) { Set<Set<? extends Type>> newDisjNormForm = new HashSet<>(this.disjNormForm); newDisjNormForm.addAll(te.disjNormForm); 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 index 61bded5236ca166dee7a2bb87f78362a3513b86b..317f3db07508526b96f83ef4299dc1dc6aadf5f8 100644 --- 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 @@ -38,9 +38,8 @@ public class TypePredicateArgumentFilterSampler<T, R extends T> extends TypePred private final String desc; @SuppressWarnings("unchecked") - public TypePredicateArgumentFilterSampler(String desc, Predicate<? super T> valuePredicate, Set<? extends R> positiveSamples, Set<?> negativeSamples, Set<Class<?>> allowedTypeSet, - boolean isNullable) { - super(valuePredicate, isNullable); + 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); @@ -68,20 +67,19 @@ public class TypePredicateArgumentFilterSampler<T, R extends T> extends TypePred 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()), - true); + 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()), true); + 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(), true); + 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, true); + 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/ValuePredicateArgumentFilterSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentFilterSampler.java index cf17d773155e154ea3d74f9b6bee05caf07661b0..b13fcca6431a62fb68517c2ad5fed0e8d3d00427 100644 --- 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 @@ -30,7 +30,6 @@ import java.util.stream.Collectors; import com.oracle.truffle.r.nodes.builtin.ValuePredicateArgumentFilter; import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler.ArgumentValueFilterSampler; -import com.sun.source.doctree.AttributeTree.ValueKind; public class ValuePredicateArgumentFilterSampler<T> extends ValuePredicateArgumentFilter<T> implements ArgumentValueFilterSampler<T> { @@ -39,9 +38,8 @@ public class ValuePredicateArgumentFilterSampler<T> extends ValuePredicateArgume 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, - boolean isNullable) { - super(valuePredicate, isNullable); + 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); @@ -69,21 +67,21 @@ public class ValuePredicateArgumentFilterSampler<T> extends ValuePredicateArgume 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), true); + 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()), true); + 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(), true); + 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, true); + 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 index 198567699625f24e3328b500745118ff3965dba6..f38dfbcdb3d82f00c2086e860ed828a2750e04b5 100644 --- 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 @@ -66,9 +66,10 @@ public class ValuePredicateArgumentMapperSampler<T, R> extends ValuePredicateArg } 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<R> resultClass) { - return new ValuePredicateArgumentMapperSampler<>(CastUtils.getPredefStepDesc(), mapper, unmapper, positiveSamples, negativeSamples, Collections.singleton(inputClass), - Collections.singleton(resultClass)); + 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 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 index 33f3ebe0ea4419c7efe1973399f1bead927710af..dc28199b3136fd0511e827aada72e6f3ea76a512 100644 --- 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 @@ -28,10 +28,10 @@ import java.util.List; import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; -import java.util.stream.Stream; 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; @@ -40,8 +40,8 @@ public class VectorPredicateArgumentFilterSampler<T extends RAbstractVector> ext private final String desc; private final List<Integer> invalidVectorSize; - public VectorPredicateArgumentFilterSampler(String desc, Predicate<T> valuePredicate, boolean isNullable, Integer... invalidVectorSize) { - super(valuePredicate, isNullable); + public VectorPredicateArgumentFilterSampler(String desc, Predicate<T> valuePredicate, Integer... invalidVectorSize) { + super(valuePredicate); this.desc = desc; this.invalidVectorSize = invalidVectorSize == null ? Collections.emptyList() : Arrays.asList(invalidVectorSize); } @@ -52,8 +52,9 @@ public class VectorPredicateArgumentFilterSampler<T extends RAbstractVector> ext return test((T) x); } else { Object v = CastUtils.singletonVector(x); - if (v == RNull.instance) { - v = null; + 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); } 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 bb690557e1b0f3050f4b633f9b3212a63aef7467..d1c7b7d074ed0c80bb58f19d9f4c25ff6ac39496 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 @@ -250,8 +250,8 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest { ((RShareable) b).incRefCount(); } - RVector aMaterialized = a.copy().materialize(); - RVector bMaterialized = b.copy().materialize(); + RVector<?> aMaterialized = a.copy().materialize(); + RVector<?> bMaterialized = b.copy().materialize(); aMaterialized.setAttr("a", "a"); bMaterialized.setAttr("b", "b"); @@ -387,6 +387,6 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest { private static NodeHandle<BinaryArithmeticNode> create(BinaryArithmeticFactory factory) { return createHandle(BinaryArithmeticNode.create(factory, null), // - (node, args) -> node.execute(null, args[0], args[1])); + (node, args) -> node.executeBuiltin(null, args[0], args[1])); } } 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 bb9b3f49054c9a39298b4f3328df2ac7864771b5..0caff997158ece3fa6b2eca40a8e449d5047de54 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 @@ -43,10 +43,10 @@ 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.builtin.RBuiltinFactory; import com.oracle.truffle.r.nodes.casts.CastNodeSampler; import com.oracle.truffle.r.nodes.casts.Samples; 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; import com.oracle.truffle.r.nodes.test.TestUtilities.NodeHandle; import com.oracle.truffle.r.nodes.unary.CastNode; @@ -54,8 +54,9 @@ import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.ResourceHandlerFactory; -import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; 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.test.TestBase; import com.oracle.truffle.r.test.generate.FastRSession; @@ -63,11 +64,33 @@ import com.oracle.truffle.r.test.generate.GnuROneShotRSession; import com.oracle.truffle.r.test.generate.TestOutputManager; import com.oracle.truffle.r.test.generate.TestOutputManager.TestInfo; +/** + * Use the following command to sweep all builtins + * + * <pre> + * mx rbdiag --sweep --mnonly --matchLevel=error --maxSweeps=30 --outMaxLev=0 + * </pre> + * + * . + * + */ class ChimneySweeping extends SingleBuiltinDiagnostics { + private Set<String> blacklistedBuiltins = new HashSet<>(); + { + blacklistedBuiltins.add(".dfltWarn"); + blacklistedBuiltins.add("browser"); + blacklistedBuiltins.add(".fastr.context.r"); + } + private static final String TEST_PREFIX = "com.oracle.truffle.r.test.builtins.TestBuiltin_"; private static final String SWEEP_MODE_ARG = "--sweep"; - private static final String SWEEP_MODE_ARG_SPEC = SWEEP_MODE_ARG + "-"; + private static final String SWEEP_MODE_ARG_SPEC = SWEEP_MODE_ARG + "="; + private static final String NO_SELF_TEST_ARG = "--noSelfTest"; + private static final String MISSING_AND_NULL_SAMPLES_ONLY_ARG = "--mnonly"; + private static final String OUTPUT_MATCH_LEVEL = "--matchLevel"; + private static final String OUTPUT_MATCH_LEVEL_SPEC = OUTPUT_MATCH_LEVEL + "="; + private static final String MAX_SWEEPS_ARG = "--maxSweeps="; enum ChimneySweepingMode { auto, @@ -85,8 +108,25 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { } } + enum OutputMatchLevel { + same, + error; + + static Optional<OutputMatchLevel> fromArg(String arg) { + if (arg.startsWith(OUTPUT_MATCH_LEVEL_SPEC)) { + return Optional.of(valueOf(arg.substring(OUTPUT_MATCH_LEVEL_SPEC.length()))); + } else { + return Optional.empty(); + } + } + } + static class ChimneySweepingConfig extends DiagConfig { ChimneySweepingMode sweepingMode; + OutputMatchLevel outputMatchLevel; + boolean missingAndNullSamplesOnly; + boolean performPipelineSelfTest; + int maxSweeps; } static class ChimneySweepingSuite extends RBuiltinDiagnostics { @@ -100,13 +140,13 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { super(config); this.diagConfig = config; - System.out.println("Loading GnuR ..."); + print(1, "Loading GnuR ..."); gnuRSession = new GnuROneShotRSession(); - System.out.println("Loading FastR ..."); + print(1, "Loading FastR ..."); fastRSession = FastRSession.create(); - System.out.println("Loading test outputs ..."); + print(1, "Loading test outputs ..."); outputManager = loadTestOutputManager(); } @@ -121,6 +161,12 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { static <C extends ChimneySweepingConfig> C initChimneySweepingConfig(C config, String[] args) { config.sweepingMode = getSweepMode(args).flatMap(ChimneySweepingMode::fromArg).orElse(ChimneySweepingMode.auto); + config.outputMatchLevel = getOutputMatchLevel(args).flatMap(OutputMatchLevel::fromArg).orElse(OutputMatchLevel.same); + config.missingAndNullSamplesOnly = Arrays.stream(args).filter(arg -> MISSING_AND_NULL_SAMPLES_ONLY_ARG.equals(arg)).findFirst().isPresent(); + // The pipeline self-test is disabled when only RMissing and RNull samples are used as + // 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); } @@ -128,9 +174,17 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { return Arrays.stream(args).filter(arg -> arg.startsWith(SWEEP_MODE_ARG)).findFirst(); } + private static Optional<String> getOutputMatchLevel(String[] args) { + return Arrays.stream(args).filter(arg -> arg.startsWith(OUTPUT_MATCH_LEVEL_SPEC)).findFirst(); + } + @Override - public SingleBuiltinDiagnostics createBuiltinDiagnostics(RBuiltinFactory bf) { - return new ChimneySweeping(this, bf); + public SingleBuiltinDiagnostics createBuiltinDiagnostics(RBuiltinDiagFactory bf) { + if (bf instanceof RIntBuiltinDiagFactory) { + return new ChimneySweeping(this, (RIntBuiltinDiagFactory) bf); + } else { + throw new UnsupportedOperationException("Only non-external builtins supported for chimney-sweeping atm"); + } } private static TestOutputManager loadTestOutputManager() throws IOException { @@ -151,13 +205,18 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { private final List<Samples<?>> argSamples; private final ChimneySweepingSuite diagSuite; private final Set<RList> validArgsList; + private final RBuiltinKind kind; private final Set<List<String>> printedOutputPairs = new HashSet<>(); private final Set<String> printedErrors = new HashSet<>(); private int sweepCounter = 0; - ChimneySweeping(ChimneySweepingSuite diagSuite, RBuiltinFactory builtinFactory) { + ChimneySweeping(ChimneySweepingSuite diagSuite, RIntBuiltinDiagFactory builtinFactory) { super(diagSuite, builtinFactory); + + print(0, "\n*** Chimney-sweeping of '" + builtinName + "' (" + builtinFactory.getBuiltinNodeClass().getName() + ") ***"); + + this.kind = builtinFactory.getBuiltinKind(); this.diagSuite = diagSuite; this.validArgsList = extractValidArgsForBuiltin(); this.argSamples = createSamples(); @@ -165,48 +224,59 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { @Override public void diagnoseBuiltin() throws Exception { - super.diagnoseBuiltin(); + // super.diagnoseBuiltin(); - sweepChimney(); + if (blacklistedBuiltins.contains(builtinName)) { + print(1, "Builtin '" + builtinName + "' blacklisted for chimney-sweeping"); + } else { + sweepChimney(); + } } @Override protected void diagnosePipeline(int i) { super.diagnosePipeline(i); - System.out.println(" Samples:"); - System.out.println(argSamples.get(i)); + print(1, " Samples:"); + print(1, argSamples.get(i)); - checkPipelines(i); + if (diagSuite.diagConfig.performPipelineSelfTest) { + checkPipelines(i); + } } @SuppressWarnings({"rawtypes", "unchecked"}) private List<Samples<?>> createSamples() { - DefaultArgsExtractor defArgExt = new DefaultArgsExtractor(diagSuite.fastRSession); + DefaultArgsExtractor defArgExt = new DefaultArgsExtractor(diagSuite.fastRSession, msg -> print(1, msg)); Map<String, Samples<?>> defaultArgs = defArgExt.extractDefaultArgs(builtinName); List<Samples<?>> as = new ArrayList<>(); for (int i = 0; i < argLength; i++) { - CastNode cn; - if (i < castNodes.length) { - cn = castNodes[i]; - } else { - cn = null; - } Samples samples; - try { - if (cn == null) { - samples = Samples.anything(); + + if (diagSuite.diagConfig.missingAndNullSamplesOnly) { + samples = Samples.anything(RNull.instance).or(Samples.anything(RMissing.instance)); + } else { + CastNode cn; + if (i < castNodes.length) { + cn = castNodes[i]; } else { - CastNodeSampler<CastNode> sampler = CastNodeSampler.createSampler(cn); - samples = sampler.collectSamples(); + cn = null; + } + try { + if (cn == null) { + samples = Samples.anything(); + } else { + CastNodeSampler<CastNode> sampler = CastNodeSampler.createSampler(cn); + samples = sampler.collectSamples(); + } + } catch (Exception e) { + throw new RuntimeException("Error in sample generation from argument " + i, e); } - } catch (Exception e) { - throw new RuntimeException("Error in sample generation from argument " + i, e); - } - Samples defArgSamples = defaultArgs.get(parameterNames[i]); - samples = defArgSamples == null ? samples : samples.and(defArgSamples); + Samples defArgSamples = defaultArgs.get(parameterNames[i]); + samples = defArgSamples == null ? samples : samples.and(defArgSamples); + } as.add(samples); @@ -232,15 +302,15 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { if (cn != null) { Samples<?> samples = argSamples.get(i); if (samples.positiveSamples().isEmpty() && samples.negativeSamples().isEmpty()) { - System.out.println("No samples"); + print(1, "No samples"); } else { testPipeline(cn, samples); - System.out.println("Pipeline check OK (" + samples.positiveSamples().size() + "," + samples.negativeSamples().size() + ")"); + print(1, "Pipeline check OK (" + samples.positiveSamples().size() + "," + samples.negativeSamples().size() + ")"); } } } - private static void testPipeline(CastNode cn, Samples<?> samples) { + private void testPipeline(CastNode cn, Samples<?> samples) { NodeHandle<CastNode> argCastNodeHandle = TestUtilities.createHandle(cn, (node, args) -> { return node.execute(args[0]); }); @@ -249,7 +319,7 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { try { argCastNodeHandle.call(sample); } catch (UnsupportedSpecializationException e) { - System.out.println("Warning: No specialization to handle arg " + sample + " : " + e.getMessage()); + print(1, "Warning: No specialization to handle arg " + sample + " : " + e.getMessage()); } catch (Exception e) { e.printStackTrace(); fail("Unexpectedly negative sample: " + sample); @@ -270,11 +340,11 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { } private Set<RList> extractValidArgsForBuiltin() { - final PolyglotEngine vm = diagSuite.fastRSession.createTestContext(null); + final PolyglotEngine vm = diagSuite.fastRSession.checkContext(null).createVM(); try { String snippetAnchor; - switch (annotation.kind()) { + switch (kind) { case INTERNAL: snippetAnchor = ".Internal(" + builtinName + "("; break; @@ -294,37 +364,24 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { a -> a != null && !"".equals(a)).collect(Collectors.toSet()); Set<RList> args = validArgs.stream().map(a -> evalValidArgs(a, vm)).filter(a -> a != null).collect(Collectors.toSet()); - if (args.isEmpty()) { - Object[] nullArgs = new Object[this.argLength]; - Arrays.fill(nullArgs, RNull.instance); - args = Collections.singleton(RDataFactory.createList(nullArgs)); - System.out.println("No suitable test snippets found. Using the default RNull argument list"); - } - return args; } finally { vm.dispose(); } } - private static RList evalValidArgs(String argsExpr, PolyglotEngine vm) { + private RList evalValidArgs(String argsExpr, PolyglotEngine vm) { try { Value eval = vm.eval(RSource.fromTextInternal(argsExpr, RSource.Internal.UNIT_TEST)); RList args = (RList) eval.get(); return args; - } catch (IOException e) { - // throw new RuntimeException(e); - // todo: warning + } catch (Exception e) { + print(1, "Warning: Cannot parse arguments: " + argsExpr); return null; } } - private void sweepChimney() throws IOException { - System.out.println("++++++++++++++++++++++"); - System.out.println("+ Chimney-sweeping +"); - System.out.println("++++++++++++++++++++++"); - System.out.println(); - + private void sweepChimney() { boolean useDiagonalGen; long totalCombinations = calculateNumOfSampleCombinations(argSamples); @@ -346,14 +403,11 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { List<List<Object>> generatedCombinations = generateSampleArgCombinations(argSamples, useDiagonalGen); - System.out.println("Springboard argument lists: " + validArgsList.size()); - System.out.println("Used sample combinations: " + generatedCombinations.size() + " (from total " + totalCombinations + ")"); - System.out.println("Sweeps to perform: " + generatedCombinations.size() * validArgsList.size()); + print(1, "Springboard argument lists: " + validArgsList.size()); + print(1, "Used sample combinations: " + generatedCombinations.size() + " (from total " + totalCombinations + ")"); - System.out.println(); - System.out.println(); - System.out.println("Press Enter to continue ..."); - System.in.read(); + int sweepsToPerform = Math.min(generatedCombinations.size() * validArgsList.size(), diagSuite.diagConfig.maxSweeps); + print(0, "Sweeps to perform: " + sweepsToPerform); evalArgsWithSampleCombinations(generatedCombinations); } @@ -361,8 +415,12 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { private void evalBuiltin(RList validArgs, List<List<Object>> argSampleCombinations) { List<List<Object>> mergedSampleAndValidArgs = mergeValidAndSampleArgs(validArgs, argSampleCombinations); + boolean isOriginal = true; for (List<Object> evalArgs : mergedSampleAndValidArgs) { - evalBuiltin(evalArgs); + if (!evalBuiltin(evalArgs, isOriginal)) { + return; + } + isOriginal = false; } } @@ -372,11 +430,18 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { validArgsList.forEach(validArgs -> evalBuiltin(validArgs, argSampleCombinations)); } - private void evalBuiltin(List<Object> args) { + private boolean evalBuiltin(List<Object> args, boolean isOriginal) { + if (sweepCounter > diagSuite.diagConfig.maxSweeps) { + return false; + } + StringBuilder sb = new StringBuilder(); try { for (int i = 0; i < args.size(); i++) { Object validArg = args.get(i); + if (validArg == RMissing.instance) { + continue; + } String deparsedValidArg; try { deparsedValidArg = RDeparse.deparse(validArg); @@ -387,39 +452,51 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { if (sb.length() != 0) { sb.append(","); } - sb.append(deparsedValidArg); + sb.append(parameterNames[i]).append('=').append(deparsedValidArg); } String call; - switch (annotation.kind()) { - case INTERNAL: - call = ".Internal(" + builtinName + "(" + sb + "))"; - break; - default: - call = builtinName + "(" + sb + ")"; - break; + if ("(".equals(builtinName)) { + call = "(" + sb + ")"; + } else { + switch (kind) { + case INTERNAL: + call = ".Internal(" + builtinName + "(" + sb + "))"; + break; + default: + call = builtinName + "(" + sb + ")"; + break; + } } String output; try { - output = diagSuite.fastRSession.eval(call, null, false); + output = diagSuite.fastRSession.eval(null, call, null, false); } catch (Throwable t) { output = "ERROR: " + t.getMessage(); } - String outputGnu = diagSuite.gnuRSession.eval(call, null, false); + String outputGnu = diagSuite.gnuRSession.eval(null, call, null, false); List<String> outputPair = Arrays.asList(output, outputGnu); - if (outputGnu.equals(output)) { + if (isOriginal && !output.equals(outputGnu)) { + // The original test may not be passing (e.g. marked by Ignored.Inknown etc.). + // Skip these arguments. + System.out.print('I'); + print(1, "Ignoring original test arguments: " + sb); + return false; + } + + if (compareOutputs(output, outputGnu)) { System.out.print('.'); } else if (!printedOutputPairs.contains(outputPair)) { - System.out.println("\n#" + sweepCounter + "> " + call); - System.out.println("\n====== FastR output ======"); - System.out.println(output); + print(0, "\n#" + sweepCounter + "> " + call); + print(0, "\n====== FastR output ======"); + print(0, output); - System.out.println("====== GnuR output ======"); - System.out.println(outputGnu); - System.out.println("=========================="); + print(0, "====== GnuR output ======"); + print(0, outputGnu); + print(0, "=========================="); printedOutputPairs.add(outputPair); } else { @@ -427,17 +504,38 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { } } catch (Throwable e) { - // throw new RuntimeException(e); - // e.printStackTrace(); if (!printedErrors.contains(e.getMessage())) { String call = ".Internal(" + builtinName + "(" + sb + "))"; - System.out.println("\n[" + sweepCounter + "]> " + call); - System.out.println("ERROR: " + e.getMessage()); + print(0, "\n[" + sweepCounter + "]> " + call); + print(0, "ERROR: " + e.getMessage()); printedErrors.add(e.getMessage()); } } finally { sweepCounter++; } + + return true; + } + + private boolean compareOutputs(String output, String outputGnu) { + switch (diagSuite.diagConfig.outputMatchLevel) { + case same: + return outputGnu.equals(output); + case error: + if (output.contains("ERROR:")) { + // FastR error + return false; + } + if (output.contains("Error") && outputGnu.contains("Error")) { + return true; + } + if (!output.contains("Error") && !outputGnu.contains("Error")) { + return true; + } + return false; + default: + throw new UnsupportedOperationException("Unsupported output match level: " + diagSuite.diagConfig.outputMatchLevel); + } } static long calculateNumOfSampleCombinations(List<Samples<?>> argSamples) { diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/DefaultArgsExtractor.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/DefaultArgsExtractor.java index d2e267b1c4a1bd206c6b8b4e1202a06fc9e7dcf2..1330c6f54b2556920131be33fd8a92ba425367df 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/DefaultArgsExtractor.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/DefaultArgsExtractor.java @@ -26,6 +26,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.function.Consumer; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.vm.PolyglotEngine; @@ -47,20 +48,24 @@ import com.oracle.truffle.r.test.generate.FastRSession; class DefaultArgsExtractor { private final FastRSession fastRSession; + private final Consumer<Object> printer; - DefaultArgsExtractor(FastRSession fastRSession) { + DefaultArgsExtractor(FastRSession fastRSession, Consumer<Object> printer) { this.fastRSession = fastRSession; + this.printer = printer; } Map<String, Samples<?>> extractDefaultArgs(String functionName) { - final PolyglotEngine vm = fastRSession.createTestContext(null); + final PolyglotEngine vm = fastRSession.checkContext(null).createVM(); + HashMap<String, Samples<?>> samplesMap = new HashMap<>(); try { - HashMap<String, Samples<?>> samplesMap = new HashMap<>(); Source source = RSource.fromTextInternal("formals(" + functionName + ")", RSource.Internal.UNIT_TEST); + Value defArgVal = vm.eval(source); + if (defArgVal.get() instanceof RPairList) { RPairList formals = (RPairList) defArgVal.get(); RStringVector names = formals.getNames(null); @@ -71,9 +76,14 @@ class DefaultArgsExtractor { if (defVal instanceof RLanguage) { String deparsedDefVal = RDeparse.deparse(defVal); - Value eval = vm.eval(RSource.fromTextInternal(deparsedDefVal, - RSource.Internal.UNIT_TEST)); - defVal = eval.get(); + try { + Value eval = vm.eval(RSource.fromTextInternal(deparsedDefVal, + RSource.Internal.UNIT_TEST)); + defVal = eval.get(); + } catch (Throwable t) { + printer.accept("Warning: Unable to evaluate the default value of argument " + name + ". Expression: " + deparsedDefVal); + continue; + } if (defVal == null) { samplesMap.put(name, Samples.anything(RNull.instance)); @@ -101,11 +111,12 @@ class DefaultArgsExtractor { } - return samplesMap; - } catch (Exception e) { - throw new RuntimeException(e); + } catch (Throwable t) { + printer.accept("Warning: Unable to evaluate formal arguments of function " + functionName); } finally { vm.dispose(); } + + return samplesMap; } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..e31dde44de60c70dff2dec4c18d88e74eabb0a4a --- /dev/null +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java @@ -0,0 +1,131 @@ +/* + * 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.test; + +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertEquals; + +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.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; +import com.oracle.truffle.r.nodes.unary.CastStringBaseNode; +import com.oracle.truffle.r.nodes.unary.ChainedCastNode; +import com.oracle.truffle.r.nodes.unary.FilterNode; +import com.oracle.truffle.r.nodes.unary.FindFirstNode; +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.env.REnvironment; + +/** + * Tests that {@link PipelineToCastNode} converts manually constructed steps into the correct cast + * nodes. + */ +public class PipelineToCastNodeTests { + @Test + public void asLogicalVector() { + CastNode pipeline = createPipeline(new CoercionStep<>(RType.Logical, false)); + CastNode castNode = assertBypassNode(pipeline); + assertTrue(castNode 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(); + 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<>(x -> x instanceof REnvironment, 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(next, FilterNode.class, CastIntegerBaseNode.class); + FindFirstNode findFirst = (FindFirstNode) ((ChainedCastNode) chain).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())); + assertTrue(expectedSecond.isInstance(((ChainedCastNode) node).getSecondCast())); + } + + private static CastNode createPipeline(PipelineStep<?, ?> lastStep) { + PipelineConfigBuilder configBuilder = new PipelineConfigBuilder("x"); + return PipelineToCastNode.convert(configBuilder.build(), lastStep); + } +} 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 1e6844fbbc770576d55ce2292a8649568836a02e..274b3ae20a7147f7ba99cf509af256b78681de26 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 @@ -23,46 +23,59 @@ package com.oracle.truffle.r.nodes.test; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.Frame; 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.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.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.PredefFiltersSamplers; -import com.oracle.truffle.r.nodes.casts.PredefMappersSamplers; 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.ArgumentsSignature; 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.RNode; public class RBuiltinDiagnostics { + private static final String OUTPUT_MAX_LEVEL_ARG = "--outMaxLev="; + static class DiagConfig { boolean verbose; boolean ignoreRNull; boolean ignoreRMissing; long maxTotalCombinations = 500L; + int outputMaxLevel; + } + + static { + PipelineConfig.setFilterFactory(FilterSamplerFactory.INSTANCE); + PipelineConfig.setMapperFactory(MapperSamplerFactory.INSTANCE); } private final DiagConfig diagConfig; @@ -79,13 +92,11 @@ public class RBuiltinDiagnostics { 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); return diagConfig; } public static void main(String[] args) throws Throwable { - Predef.setPredefFilters(new PredefFiltersSamplers()); - Predef.setPredefMappers(new PredefMappersSamplers()); - RBuiltinDiagnostics rbDiag = ChimneySweepingSuite.createChimneySweepingSuite(args).orElseGet(() -> createRBuiltinDiagnostics(args)); List<String> bNames = Arrays.stream(args).filter(arg -> !arg.startsWith("-")).collect(Collectors.toList()); @@ -98,22 +109,29 @@ public class RBuiltinDiagnostics { } } - public SingleBuiltinDiagnostics createBuiltinDiagnostics(RBuiltinFactory bf) { + public SingleBuiltinDiagnostics createBuiltinDiagnostics(RBuiltinDiagFactory bf) { return new SingleBuiltinDiagnostics(this, bf); } public void diagnoseSingleBuiltin(String builtinName) throws Exception { BasePackage bp = new BasePackage(); RBuiltinFactory bf = bp.lookupByName(builtinName); + RBuiltinDiagFactory bdf; if (bf == null) { - System.out.println("No builtin '" + builtinName + "' found"); - return; + try { + bdf = RExtBuiltinDiagFactory.create(builtinName); + } catch (Exception e) { + print(0, "No builtin '" + builtinName + "' found"); + return; + } + } else { + bdf = new RIntBuiltinDiagFactory(bf); } - createBuiltinDiagnostics(bf).diagnoseBuiltin(); + createBuiltinDiagnostics(bdf).diagnoseBuiltin(); - System.out.println("Finished"); - System.out.println("--------"); + print(0, "Finished"); + print(0, "--------"); System.exit(0); } @@ -122,42 +140,45 @@ public class RBuiltinDiagnostics { BasePackage bp = new BasePackage(); for (RBuiltinFactory bf : bp.getBuiltins().values()) { try { - createBuiltinDiagnostics(bf).diagnoseBuiltin(); + createBuiltinDiagnostics(new RIntBuiltinDiagFactory((bf))).diagnoseBuiltin(); } catch (Exception e) { - System.out.println(bf.getName() + " failed: " + e.getMessage()); + e.printStackTrace(); + print(0, bf.getName() + " failed: " + e.getMessage()); } } - System.out.println("Finished"); - System.out.println("--------"); + print(0, "Finished"); + print(0, "--------"); System.exit(0); } + protected void print(int level, Object x) { + if (level <= diagConfig.outputMaxLevel) { + System.out.println(x); + } + } + static class SingleBuiltinDiagnostics { private final RBuiltinDiagnostics diagSuite; - final RBuiltinFactory builtinFactory; + final RBuiltinDiagFactory builtinFactory; final String builtinName; final int argLength; final String[] parameterNames; final CastNode[] castNodes; - final Class<?> builtinClass; - final RBuiltin annotation; final List<Method> specMethods; final List<TypeExpr> argResultSets; final HashMap<Method, List<Set<Cast>>> convResultTypePerSpec; final Set<List<Type>> nonCoveredArgsSet; - SingleBuiltinDiagnostics(RBuiltinDiagnostics diagSuite, RBuiltinFactory builtinFactory) { + SingleBuiltinDiagnostics(RBuiltinDiagnostics diagSuite, RBuiltinDiagFactory builtinFactory) { this.diagSuite = diagSuite; this.builtinFactory = builtinFactory; - this.builtinName = builtinFactory.getName(); + this.builtinName = builtinFactory.getBuiltinName(); - this.builtinClass = builtinFactory.getBuiltinNodeClass(); - this.annotation = builtinClass.getAnnotation(RBuiltin.class); - this.argLength = annotation.parameterNames().length; - String[] pn = annotation.parameterNames(); - this.parameterNames = Arrays.stream(pn).map(n -> n.isEmpty() ? null : n).toArray(String[]::new); + 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(); @@ -166,12 +187,16 @@ public class RBuiltinDiagnostics { return !((diagSuite.diagConfig.ignoreRNull && t == RNull.class) || (diagSuite.diagConfig.ignoreRMissing && t == RMissing.class)); })).collect(Collectors.toList()); - this.specMethods = CastUtils.getAnnotatedMethods(builtinClass, Specialization.class); + this.specMethods = CastUtils.getAnnotatedMethods(builtinFactory.getBuiltinNodeClass(), Specialization.class); this.convResultTypePerSpec = createConvResultTypePerSpecialization(); this.nonCoveredArgsSet = combineArguments(); } + protected void print(int level, Object x) { + diagSuite.print(level, x); + } + private HashMap<Method, List<Set<Cast>>> createConvResultTypePerSpecialization() { HashMap<Method, List<Set<Cast>>> convResultTypes = new HashMap<>(); @@ -204,60 +229,72 @@ public class RBuiltinDiagnostics { } public void diagnoseBuiltin() throws Exception { - System.out.println("****************************************************************************"); - System.out.println("Builtin: " + builtinName + " (" + builtinFactory.getBuiltinNodeClass().getName() + ")"); - System.out.println("****************************************************************************"); + print(0, "****************************************************************************"); + print(0, "Builtin: " + builtinName + " (" + builtinFactory.getBuiltinNodeClass().getName() + ")"); + print(0, "****************************************************************************"); - System.out.println("Argument cast pipelines binding:"); + print(0, "Argument cast pipelines binding:"); for (int i = 0; i < argLength; i++) { diagnosePipeline(i); } - System.out.println("\nUnhandled argument combinations: " + nonCoveredArgsSet.size()); - System.out.println(""); + print(0, "\nUnhandled argument combinations: " + nonCoveredArgsSet.size()); + print(0, ""); + + printDeadSpecs(); if (diagSuite.diagConfig.verbose) { for (List<Type> uncoveredArgs : nonCoveredArgsSet) { - System.out.println(uncoveredArgs.stream().map(t -> typeName(t)).collect(Collectors.toList())); + print(0, uncoveredArgs.stream().map(t -> typeName(t)).collect(Collectors.toList())); } } } + private void printDeadSpecs() { + print(0, "Dead specializations: "); + for (Map.Entry<Method, List<Set<Cast>>> resTpPerSpec : convResultTypePerSpec.entrySet()) { + List<Set<Cast>> argsCasts = resTpPerSpec.getValue(); + List<Integer> missingCasts = new ArrayList<>(); + for (int i = 0; i < argsCasts.size(); i++) { + Set<Cast> argCasts = argsCasts.get(i); + if (argCasts.isEmpty()) { + missingCasts.add(i); + } + } + + if (!missingCasts.isEmpty()) { + print(0, " " + methodName(resTpPerSpec.getKey(), missingCasts)); + } + } + + print(0, ""); + } + protected void diagnosePipeline(int i) { TypeExpr argResultSet = argResultSets.get(i); - System.out.println("\n Pipeline for '" + annotation.parameterNames()[i] + "' (arg[" + i + "]):"); - System.out.println(" Result types union:"); + print(0, "\n Pipeline for '" + parameterNames[i] + "' (arg[" + i + "]):"); + print(0, " Result types union:"); Set<Type> argSetNorm = argResultSet.normalize(); - System.out.println(" " + argSetNorm.stream().map(argType -> typeName(argType)).collect(Collectors.toSet())); - System.out.println(" Bound result types:"); + print(0, " " + argSetNorm.stream().map(argType -> typeName(argType)).collect(Collectors.toSet())); + print(0, " Bound result types:"); 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 -> { - System.out.println(" " + partialCast.coverage() + " (" + typeName(partialCast.inputType()) + "->" + typeName(partialCast.resultType()) + ")" + " in " + - methodName(entry.getKey(), curParIndex)); + print(0, " " + partialCast.coverage() + " (" + typeName(partialCast.inputType()) + "->" + typeName(partialCast.resultType()) + ")" + " in " + + methodName(entry.getKey(), Collections.singleton(curParIndex))); unboundArgTypes.remove(partialCast.inputType()); }); } - System.out.println(" Unbound types:"); - System.out.println(" " + unboundArgTypes.stream().map(argType -> typeName(argType)).collect(Collectors.toSet())); + print(0, " Unbound types:"); + print(0, " " + unboundArgTypes.stream().map(argType -> typeName(argType)).collect(Collectors.toSet())); } private CastNode[] getCastNodesFromBuiltin() { - ArgumentsSignature signature = ArgumentsSignature.get(parameterNames); - - int total = signature.getLength(); - RNode[] args = new RNode[total]; - for (int i = 0; i < total; i++) { - args[i] = ReadVariableNode.create("dummy"); - } - RBuiltinNode builtinNode = builtinFactory.getConstructor().apply(args.clone()); - - CastNode[] cn = builtinNode.getCasts(); - return cn; + return builtinFactory.getCasts(); } private List<TypeExpr> createArgResultSets() { @@ -300,13 +337,13 @@ public class RBuiltinDiagnostics { } } - private static String methodName(Method m, int markedParamIndex) { - final int markedParamRealIndex = getRealParamIndex(m.getParameterTypes(), markedParamIndex); + private static String methodName(Method m, Collection<Integer> markedParamIndices) { + final Set<Integer> markedParamRealIndices = markedParamIndices.stream().map(markedParamIndex -> getRealParamIndex(m.getParameterTypes(), markedParamIndex)).collect(Collectors.toSet()); StringBuilder sb = new StringBuilder(); int i = 0; for (Class<?> pt : m.getParameterTypes()) { final String tn; - if (i == markedParamRealIndex) { + if (markedParamRealIndices.contains(i)) { tn = "*" + typeName(pt) + "*"; } else { tn = typeName(pt); @@ -320,4 +357,123 @@ public class RBuiltinDiagnostics { } return typeName(m.getReturnType()) + " " + m.getName() + "(" + sb + ")"; } + + public interface RBuiltinDiagFactory { + String getBuiltinName(); + + Class<?> getBuiltinNodeClass(); + + String[] getParameterNames(); + + CastNode[] getCasts(); + + } + + public static final class RIntBuiltinDiagFactory implements RBuiltinDiagFactory { + + private final RBuiltinFactory fact; + + public RIntBuiltinDiagFactory(RBuiltinFactory fact) { + super(); + this.fact = fact; + } + + @Override + public String getBuiltinName() { + return fact.getName(); + } + + @Override + public Class<?> getBuiltinNodeClass() { + return fact.getBuiltinNodeClass(); + } + + public RBuiltinKind getBuiltinKind() { + return fact.getKind(); + } + + @Override + public String[] getParameterNames() { + RBuiltin annotation = fact.getBuiltinNodeClass().getAnnotation(RBuiltin.class); + String[] pn = annotation.parameterNames(); + return Arrays.stream(pn).map(n -> n.isEmpty() ? null : n).toArray(String[]::new); + } + + @Override + public CastNode[] getCasts() { + ArgumentsSignature signature = ArgumentsSignature.get(getParameterNames()); + + int total = signature.getLength(); + RNode[] args = new RNode[total]; + for (int i = 0; i < total; i++) { + args[i] = ReadVariableNode.create("dummy"); + } + + return fact.getConstructor().apply(args).getCasts(); + } + + } + + public static final class RExtBuiltinDiagFactory implements RBuiltinDiagFactory { + + private final Class<? extends RExternalBuiltinNode> nodeClass; + private final String[] parameterNames; + + RExtBuiltinDiagFactory(Class<? extends RExternalBuiltinNode> nodeClass, int arity) { + this.nodeClass = nodeClass; + this.parameterNames = new String[arity]; + for (int i = 0; i < arity; i++) { + this.parameterNames[i] = "arg" + i; + } + } + + @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); + } + } + + if (!RExternalBuiltinNode.class.isAssignableFrom(nodeClass)) { + throw new IllegalArgumentException(extBuiltinClsName + " is not a subclass of " + RExternalBuiltinNode.class.getName()); + } + + Optional<Method> execMethod = Arrays.stream(nodeClass.getMethods()).filter( + m -> m.getName().equals("execute") && Arrays.stream(m.getParameterTypes()).allMatch(t -> t == Object.class)).findFirst(); + if (execMethod.isPresent()) { + return new RExtBuiltinDiagFactory((Class<RExternalBuiltinNode>) nodeClass, execMethod.get().getParameterCount()); + } else { + throw new UnsupportedOperationException(extBuiltinClsName + " is not a supported external builtin class"); + } + } + + @Override + public String getBuiltinName() { + return nodeClass.getSimpleName(); + } + + @Override + public Class<?> getBuiltinNodeClass() { + return nodeClass; + } + + @Override + public String[] getParameterNames() { + return parameterNames; + } + + @Override + public CastNode[] getCasts() { + try { + return ((RExternalBuiltinNode) nodeClass.getMethod("create").invoke(null)).getCasts(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + } diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestBase.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestBase.java index abd1f3fab05b824fbd86294ccaff489811b72ba1..fb3d6438bb838b249a65d8e67901278432d03ce1 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestBase.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestBase.java @@ -22,8 +22,6 @@ */ package com.oracle.truffle.r.nodes.test; -import java.io.IOException; - import org.junit.AfterClass; import org.junit.BeforeClass; @@ -39,8 +37,8 @@ public class TestBase { static RContext testVMContext; @BeforeClass - public static void setupClass() throws IOException { - testVM = FastRSession.create().createTestContext(null); + public static void setupClass() { + testVM = FastRSession.create().checkContext(null).createVM(); testVMContext = testVM.eval(FastRSession.GET_CONTEXT).as(RContext.class); } @@ -48,7 +46,7 @@ public class TestBase { private static final Source CLEAR_WARNINGS = RSource.fromTextInternal("assign('last.warning', NULL, envir = baseenv())", RSource.Internal.CLEAR_WARNINGS); @AfterClass - public static void finishClass() throws IOException { + public static void finishClass() { testVM.eval(CLEAR_WARNINGS); testVM.dispose(); } 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 06517db953cda1e7de5b47a578c606539a8a7a41..80bf53c93e4ed277799a2abe8485b1a1ca59694e 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 @@ -22,10 +22,6 @@ */ package com.oracle.truffle.r.nodes.test; -import java.io.Closeable; -import java.io.IOException; - -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; @@ -37,6 +33,7 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.ReturnException; import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.context.RContext.RCloseable; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RNull; @@ -184,11 +181,8 @@ public class TestUtilities { @SuppressWarnings("try") public Object call(Object... args) { - try (Closeable c = RContext.withinContext(TestBase.testVMContext)) { + try (RCloseable c = RContext.withinContext(TestBase.testVMContext)) { return target.call(RArguments.createUnitialized((Object) args)); - } catch (IOException e) { - CompilerDirectives.transferToInterpreter(); - throw new RuntimeException(e); } } } 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 caf3f27d52dbc46a48bd6270f80e63733b86e498..731c23a0b23818a2357f1205027ed773e92f65d9 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 @@ -150,7 +150,7 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest { ((RShareable) a).incRefCount(); } - RVector aMaterialized = a.copy().materialize(); + RVector<?> aMaterialized = a.copy().materialize(); aMaterialized.setAttr("a", "a"); assertAttributes(executeArithmetic(factory, aMaterialized.copy()), "a"); } 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 new file mode 100644 index 0000000000000000000000000000000000000000..32540f59b3e7d34604b2bb8d25f66085726b98cc --- /dev/null +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/BypassNodeGenSampler.java @@ -0,0 +1,78 @@ +/* + * 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.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) { + TypeExpr rt = wrappedHeadSampler == null ? TypeExpr.ANYTHING : wrappedHeadSampler.resultTypes(inputTypes); + 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 index 75b90e8b9bf3a67d66b91c7af452f0715dcaa9f0..f1d3b69b7d5f4090414a54453c29c309a301a134 100644 --- 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 @@ -46,7 +46,7 @@ public class CastToVectorNodeGenSampler extends CastNodeSampler<CastToVectorNode @Override public TypeExpr resultTypes(TypeExpr inputType) { List<Cast> castList; - if (castNode.isNonVectorPreserved()) { + if (castNode.isPreserveNonVector()) { castList = Arrays.asList(new Cast(RNull.class, RNull.class), new Cast(RMissing.class, RNull.class), new Cast(RFunction.class, RFunction.class), 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 index 047ced6cff65c7bf52f15672ccd52189a42737da..c4f488fc00c49189f157885f749f29c7dfbf8c4c 100644 --- 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 @@ -24,7 +24,6 @@ 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.CastUtils; import com.oracle.truffle.r.nodes.casts.Samples; import com.oracle.truffle.r.nodes.casts.TypeExpr; @@ -55,10 +54,13 @@ public class FilterNodeGenSampler extends CastNodeSampler<FilterNodeGen> { @SuppressWarnings("unchecked") @Override public Samples<?> collectSamples(TypeExpr inputType, Samples<?> downStreamSamples) { - Samples samples = filter.collectSamples(inputType); - samples = isWarning ? samples.positiveOnly() : samples; - Samples<?> combined = samples.and(downStreamSamples); - return combined; - } + 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 index 3fa48e1f4a8e503607ae54d9135563aa65e32f56..41c209dffdb66291a1e90a5e2d980801ad43e158 100644 --- 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 @@ -24,9 +24,7 @@ package com.oracle.truffle.r.nodes.unary; import java.lang.reflect.Type; 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; @@ -36,7 +34,6 @@ 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.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; public class FindFirstNodeGenSampler extends CastNodeSampler<FindFirstNodeGen> { @@ -118,16 +115,19 @@ public class FindFirstNodeGenSampler extends CastNodeSampler<FindFirstNodeGen> { @Override public TypeExpr resultTypes(TypeExpr inputType) { + TypeExpr rt; if (elementClass == null || elementClass == Object.class) { if (inputType.isAnything()) { - return TypeExpr.atom(RAbstractVector.class).not(); + rt = TypeExpr.atom(RAbstractVector.class).not(); } else { Set<Type> resTypes = inputType.classify().stream().map(c -> CastUtils.elementType(c)).collect(Collectors.toSet()); - return TypeExpr.union(resTypes); + rt = TypeExpr.union(resTypes); } } else { - return TypeExpr.atom(elementClass); + rt = TypeExpr.atom(elementClass); } + + return rt; } } diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/MapNodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/MapNodeSampler.java similarity index 93% rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/MapNodeGenSampler.java rename to com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/MapNodeSampler.java index 0c0844548b4bb2359722ee9172e4b8b0ba67be95..1377ac3fc050fd79d3ae51ebbe837ed76c1dceed 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/MapNodeGenSampler.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/MapNodeSampler.java @@ -28,11 +28,11 @@ import com.oracle.truffle.r.nodes.casts.Samples; import com.oracle.truffle.r.nodes.casts.TypeExpr; @SuppressWarnings({"rawtypes", "unchecked"}) -public class MapNodeGenSampler extends CastNodeSampler<MapNodeGen> { +public class MapNodeSampler extends CastNodeSampler<MapNode> { private final ArgumentMapperSampler mapFn; - public MapNodeGenSampler(MapNodeGen castNode) { + public MapNodeSampler(MapNode castNode) { super(castNode); assert castNode.getMapper() instanceof ArgumentMapperSampler; this.mapFn = (ArgumentMapperSampler) castNode.getMapper(); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/CallInlineCacheNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/CallInlineCacheNode.java deleted file mode 100644 index 6bffe4ce0c9fc7181d61d8afcdc0ff94efbab026..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/CallInlineCacheNode.java +++ /dev/null @@ -1,61 +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.nodes; - -import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; -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.DirectCallNode; -import com.oracle.truffle.api.nodes.IndirectCallNode; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; - -/** - * This node reifies a runtime object into the AST by creating nodes for frequently encountered - * values. This can be used to bridge the gap between code as runtime data and executed code. - */ -public abstract class CallInlineCacheNode extends RBaseNode { - - protected static final int CACHE_LIMIT = 2; - - public abstract Object execute(VirtualFrame frame, CallTarget target, Object[] arguments); - - protected static DirectCallNode createDirectCallNode(CallTarget target) { - return Truffle.getRuntime().createDirectCallNode(target); - } - - @Specialization(guards = "target == callNode.getCallTarget()", limit = "CACHE_LIMIT") - protected Object call(VirtualFrame frame, @SuppressWarnings("unused") CallTarget target, Object[] arguments, @Cached("createDirectCallNode(target)") DirectCallNode callNode) { - return callNode.call(frame, arguments); - } - - protected static IndirectCallNode createIndirectCallNode() { - return Truffle.getRuntime().createIndirectCallNode(); - } - - @Specialization - protected Object call(VirtualFrame frame, CallTarget target, Object[] arguments, @Cached("createIndirectCallNode()") IndirectCallNode callNode) { - return callNode.call(frame, target, arguments); - } -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/EmptyTypeSystemFlatLayout.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/EmptyTypeSystemFlatLayout.java new file mode 100644 index 0000000000000000000000000000000000000000..63903c8fcb91bd1a727bbf14770a2cc0b2c8a527 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/EmptyTypeSystemFlatLayout.java @@ -0,0 +1,37 @@ +/* + * 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; + +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; + +/** + * Auxiliary class for nodes that want to use the new DSL layout with no implicit type conversions. + */ +@TypeSystem +@DSLOptions(defaultGenerator = FLAT) +public class EmptyTypeSystemFlatLayout { + // empty +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/InlineCacheNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/InlineCacheNode.java index 3e08b161d10870f99c1b4a084cfc6b4d7aa5de7a..257db87ef50139aa820860f3da170204fa0117e9 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/InlineCacheNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/InlineCacheNode.java @@ -22,7 +22,6 @@ */ package com.oracle.truffle.r.nodes; -import java.util.function.BiFunction; import java.util.function.Function; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -40,6 +39,7 @@ import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RPromise.Closure; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.TruffleBiFunction; /** * This node reifies a runtime object into the AST by creating nodes for frequently encountered @@ -49,11 +49,11 @@ public abstract class InlineCacheNode extends RBaseNode { protected final int maxPicDepth; private final Function<Object, RNode> reify; - private final BiFunction<Frame, Object, Object> generic; + private final TruffleBiFunction<Frame, Object, Object> generic; public abstract Object execute(Frame frame, Object value); - InlineCacheNode(int maxPicDepth, Function<Object, RNode> reify, BiFunction<Frame, Object, Object> generic) { + InlineCacheNode(int maxPicDepth, Function<Object, RNode> reify, TruffleBiFunction<Frame, Object, Object> generic) { this.maxPicDepth = maxPicDepth; this.reify = reify; this.generic = generic; @@ -92,8 +92,8 @@ public abstract class InlineCacheNode extends RBaseNode { * inline cache has reached its maximum size */ @SuppressWarnings("unchecked") - public static <T> InlineCacheNode createCache(int maxPicDepth, Function<T, RNode> reify, BiFunction<Frame, T, Object> generic) { - return InlineCacheNodeGen.create(maxPicDepth, (Function<Object, RNode>) reify, (BiFunction<Frame, Object, Object>) generic); + public static <T> InlineCacheNode createCache(int maxPicDepth, Function<T, RNode> reify, TruffleBiFunction<Frame, T, Object> generic) { + return InlineCacheNodeGen.create(maxPicDepth, (Function<Object, RNode>) reify, (TruffleBiFunction<Frame, Object, Object>) generic); } /** diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java index 9fd030097191ab7bee93e4cd421bd6b6e9783efe..c41e75bf18234033e96c8c6a11cfa91179c8b110 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java @@ -47,6 +47,7 @@ import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; import com.oracle.truffle.r.nodes.function.FunctionExpressionNode; import com.oracle.truffle.r.nodes.function.PostProcessArgumentsNode; import com.oracle.truffle.r.nodes.function.RCallNode; +import com.oracle.truffle.r.nodes.function.RCallSpecialNode; import com.oracle.truffle.r.nodes.function.SaveArgumentsNode; import com.oracle.truffle.r.nodes.function.WrapDefaultArgumentNode; import com.oracle.truffle.r.nodes.unary.GetNonSharedNodeGen; @@ -57,6 +58,7 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.FastPathFactory; import com.oracle.truffle.r.runtime.data.REmpty; +import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.EvaluatedArgumentsVisitor; import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; @@ -145,7 +147,7 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { arg -> (arg.value == null && arg.name == null) ? ConstantNode.create(arg.source == null ? RSyntaxNode.SOURCE_UNAVAILABLE : arg.source, REmpty.instance) : arg.value).toArray( RSyntaxNode[]::new); - return RCallNode.createCall(source, lhs.asRNode(), signature, nodes); + return RCallSpecialNode.createCall(source, lhs.asRNode(), signature, nodes); } private RSyntaxNode createReplacement(SourceSection source, String operator, boolean isSuper, RSyntaxNode replacementLhs, RSyntaxNode replacementRhs) { @@ -203,7 +205,7 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { * {@code newLhs}, its target turned into an update function ("foo<-"), with the given value * added to the arguments list. */ - private RCallNode createFunctionUpdate(SourceSection source, RSyntaxNode newLhs, RSyntaxNode rhs, RSyntaxCall fun) { + private RNode createFunctionUpdate(SourceSection source, RSyntaxNode newLhs, RSyntaxNode rhs, RSyntaxCall fun) { RSyntaxElement[] arguments = fun.getSyntaxArguments(); ArgumentsSignature signature = fun.getSyntaxSignature(); @@ -223,8 +225,7 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { 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 + // to work properly argNodes[0] = GetNonSharedNodeGen.create(argNodes[0].asRNode()); } newSyntaxLHS = lookup(lookupLHS.getSourceSection(), symbol + "<-", true); @@ -237,7 +238,7 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { newArgs[1] = lookup(oldArgs[1].getSourceSection(), ((RSyntaxLookup) oldArgs[1]).getIdentifier() + "<-", true); newSyntaxLHS = RCallNode.createCall(callLHS.getSourceSection(), ((RSyntaxNode) callLHS.getSyntaxLHS()).asRNode(), callLHS.getSyntaxSignature(), newArgs); } - return RCallNode.createCall(source, newSyntaxLHS.asRNode(), ArgumentsSignature.get(names), argNodes); + return RCallSpecialNode.createCall(source, newSyntaxLHS.asRNode(), ArgumentsSignature.get(names), argNodes).asRNode(); } /* @@ -287,15 +288,18 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { RSyntaxElement current = lhs; while (!(current instanceof RSyntaxLookup)) { if (!(current instanceof RSyntaxCall)) { - throw RError.error(RError.NO_CALLER, RError.Message.NON_LANG_ASSIGNMENT_TARGET); + if (current instanceof RSyntaxConstant && ((RSyntaxConstant) current).getValue() == RNull.instance) { + throw RError.error(RError.NO_CALLER, RError.Message.INVALID_LHS, "NULL"); + } else { + throw RError.error(RError.NO_CALLER, RError.Message.NON_LANG_ASSIGNMENT_TARGET); + } } RSyntaxCall call = (RSyntaxCall) current; calls.add(call); RSyntaxElement syntaxLHS = call.getSyntaxLHS(); if (call.getSyntaxArguments().length == 0 || !(syntaxLHS instanceof RSyntaxLookup || isNamespaceLookupCall(syntaxLHS))) { - // TODO: this should only be signaled when run, not when parsed - throw RInternalError.unimplemented("proper error message for RError.INVALID_LHS"); + return new ReplacementNode.LHSError(source, operator, new RSyntaxElement[]{lhs, rhs}); } current = call.getSyntaxArguments()[0]; } @@ -317,12 +321,12 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { * Create the update calls, for "a(b(x)) <- z", this would be `a<-` and `b<-`. */ for (int i = 0; i < calls.size(); i++) { - RCallNode update = createFunctionUpdate(source, ReadVariableNode.create("*tmp*" + (tempNamesIndex + i + 1)), ReadVariableNode.create("*tmpr*" + (tempNamesIndex + i - 1)), + RNode update = createFunctionUpdate(source, ReadVariableNode.create("*tmp*" + (tempNamesIndex + i + 1)), ReadVariableNode.create("*tmpr*" + (tempNamesIndex + i - 1)), calls.get(i)); if (i < calls.size() - 1) { instructions.add(WriteVariableNode.createAnonymous("*tmpr*" + (tempNamesIndex + i), update, WriteVariableNode.Mode.INVISIBLE)); } else { - instructions.add(WriteVariableNode.createAnonymous(variable.getIdentifier(), update, WriteVariableNode.Mode.INVISIBLE, isSuper)); + instructions.add(WriteVariableNode.createAnonymous(variable.getIdentifier(), update, WriteVariableNode.Mode.REGULAR, isSuper)); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java index c03f9663f35a5d1dce446f0192b8e173ed3ef375..3a07678234bf7670ccbad5709933ce23b5b8d0e7 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java @@ -33,11 +33,13 @@ import com.oracle.truffle.r.nodes.access.ReadVariadicComponentNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.PromiseNode.VarArgNode; +import com.oracle.truffle.r.nodes.function.RCallBaseNode; import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.nodes.function.WrapArgumentBaseNode; import com.oracle.truffle.r.nodes.function.WrapArgumentNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RInternalError; +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.RLanguage; @@ -47,6 +49,9 @@ import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RInstrumentableNode; 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.RSyntaxFunction; import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @@ -117,32 +122,31 @@ public class RASTUtils { * Creates a standard {@link ReadVariableNode}. */ @TruffleBoundary - public static ReadVariableNode createReadVariableNode(String name) { - return ReadVariableNode.create(name); + public static RSyntaxNode createReadVariableNode(String name) { + return RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, name, false); } /** - * Handles constants and symbols as special cases as required by R. + * Handles constants and symbols as special cases as required by R: create symbols for simple + * variables and actual values for constants. */ @TruffleBoundary - public static Object createLanguageElement(RBaseNode argNode) { - if (argNode == null) { - return RSymbol.MISSING; - } else if (argNode instanceof ConstantNode) { - Object value = ((ConstantNode) argNode).getValue(); + public static Object createLanguageElement(RSyntaxNode element) { + assert element != null; + if (element instanceof RSyntaxConstant) { + Object value = ((RSyntaxConstant) element).getValue(); if (value == RMissing.instance) { // special case which GnuR handles as an unnamed symbol return RSymbol.MISSING; } return value; - } else if (argNode instanceof ReadVariableNode) { - return RASTUtils.createRSymbol(argNode); - } else if (argNode instanceof VarArgNode) { - VarArgNode varArgNode = (VarArgNode) argNode; - return RDataFactory.createSymbolInterned(varArgNode.getIdentifier()); + } else if (element instanceof RSyntaxLookup) { + String id = ((RSyntaxLookup) element).getIdentifier(); + assert id == id.intern() : element; + return RDataFactory.createSymbol(id); } else { - assert !(argNode instanceof VarArgNode); - return RDataFactory.createLanguage((RNode) argNode); + assert element instanceof RSyntaxCall || element instanceof RSyntaxFunction; + return RDataFactory.createLanguage(element.asRNode()); } } @@ -162,20 +166,6 @@ public class RASTUtils { } } - /** - * Checks wheter {@code expr instanceof RSymbol} and, if so, wraps in an {@link RLanguage} - * instance. - */ - @TruffleBoundary - public static Object checkForRSymbol(Object expr) { - if (expr instanceof RSymbol) { - String symbolName = ((RSymbol) expr).getName(); - return RDataFactory.createLanguage(ReadVariableNode.create(symbolName)); - } else { - return expr; - } - } - /** * Create an {@link RNode} from a runtime value. */ @@ -184,7 +174,7 @@ public class RASTUtils { if (value instanceof RNode) { return (RNode) value; } else if (value instanceof RSymbol) { - return RASTUtils.createReadVariableNode(((RSymbol) value).getName()); + return RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, ((RSymbol) value).getName(), false).asRNode(); } else if (value instanceof RLanguage) { RLanguage l = (RLanguage) value; return RASTUtils.cloneNode(l.getRep()); @@ -234,8 +224,8 @@ public class RASTUtils { SourceSection sourceSection = sourceUnavailable ? RSyntaxNode.SOURCE_UNAVAILABLE : RSyntaxNode.EAGER_DEPARSE; if (fn instanceof ReadVariableNode) { return RCallNode.createCall(sourceSection, (ReadVariableNode) fn, signature, arguments); - } else if (fn instanceof RCallNode) { - return RCallNode.createCall(sourceSection, (RCallNode) fn, signature, arguments); + } else if (fn instanceof RCallBaseNode) { + return RCallNode.createCall(sourceSection, (RCallBaseNode) fn, signature, arguments); } else { // apart from RFunction, this of course would not make much sense if trying to evaluate // this call, yet it's syntactically possible, for example as a result of: diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java index 02dbbaf855144c918ced61076866063bb38648c5..15d687d6799438879e7d85a67c0a1d1ff06a3f96 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java @@ -138,10 +138,7 @@ public final class AccessArgumentNode extends RNode { private Object doArgument(VirtualFrame frame, Object arg) { if (hasDefaultArg) { - if (isMissingProfile.profile(arg == RMissing.instance)) { - return doArgumentInternal(frame); - } - if (isEmptyProfile.profile(arg == REmpty.instance)) { + if (isMissingProfile.profile(arg == RMissing.instance) || isEmptyProfile.profile(arg == REmpty.instance)) { return doArgumentInternal(frame); } } 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 b808a98d1ff98a8fef89ca805a49527920db281d..deb90eb6641880a7f0b5834f9f7ebd219453608d 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 @@ -50,9 +50,10 @@ public abstract class AccessSlotNode extends RNode { public abstract Object executeAccess(Object o, String name); - private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); @Child private ClassHierarchyNode classHierarchy; @Child private TypeofNode typeofNode; + + private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); private final BranchProfile noSlot = BranchProfile.create(); private final BranchProfile symbolValue = BranchProfile.create(); private final boolean asOperator; @@ -120,7 +121,7 @@ public abstract class AccessSlotNode extends RNode { @Specialization(contains = "getSlotS4Cached", guards = "slotAccessAllowed(object)") protected Object getSlotS4(RAttributable object, String name) { - String internedName = name.intern(); + String internedName = Utils.intern(name); Object value = object.getAttr(attrProfiles, internedName); return getSlotS4Internal(object, internedName, value); } 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 b880d98d8649d7eb23de404bc596058810cec6e5..98ed65cc09722ad911098ba83ea80dae38fd6c05 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 @@ -48,10 +48,11 @@ import com.oracle.truffle.r.runtime.nodes.RNode; */ abstract class BaseWriteVariableNode extends WriteVariableNode { + private final ConditionProfile isObjectProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile isCurrentProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile isShareableProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile isSharedProfile = ConditionProfile.createBinaryProfile(); - private final ConditionProfile isRefCountUpdateable = ConditionProfile.createBinaryProfile(); + private final ConditionProfile isSharedPermanent = ConditionProfile.createBinaryProfile(); private final BranchProfile initialSetKindProfile = BranchProfile.create(); @@ -89,18 +90,18 @@ abstract class BaseWriteVariableNode extends WriteVariableNode { // this comparison does not work consistently for boxing objects, so it's important // to do the RShareable check first. - if (isCurrentProfile.profile(isCurrentValue(frame, frameSlot, value))) { + if (isCurrentValue(frame, frameSlot, value)) { return value; } RShareable rShareable = (RShareable) shareableProfile.profile(value); if (mode == Mode.COPY) { return rShareable.copy(); } else { - if (isRefCountUpdateable.profile(!rShareable.isSharedPermanent())) { + if (!isSharedPermanent.profile(rShareable.isSharedPermanent())) { if (isSuper) { // if non-local assignment, increment conservatively rShareable.incRefCount(); - } else if (isSharedProfile.profile(!rShareable.isShared())) { + } else if (!isSharedProfile.profile(rShareable.isShared())) { // don't increment if already shared - will not get "unshared" until // this function exits anyway rShareable.incRefCount(); @@ -112,9 +113,9 @@ abstract class BaseWriteVariableNode extends WriteVariableNode { return value; } - private static boolean isCurrentValue(Frame frame, FrameSlot frameSlot, Object value) { + private boolean isCurrentValue(Frame frame, FrameSlot frameSlot, Object value) { try { - return frame.isObject(frameSlot) && frame.getObject(frameSlot) == value; + return isObjectProfile.profile(frame.isObject(frameSlot)) && isCurrentProfile.profile(frame.getObject(frameSlot) == value); } catch (FrameSlotTypeException ex) { throw RInternalError.shouldNotReachHere(); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ConstantNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ConstantNode.java index e7b17317c98683c229cd58afcb8d281a9b34f8c7..2553a52016543b6758b72bf9aaf666fd26ca8d4a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ConstantNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ConstantNode.java @@ -24,10 +24,10 @@ package com.oracle.truffle.r.nodes.access; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RSerialize; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RPromise; @@ -40,6 +40,8 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; public abstract class ConstantNode extends RSourceSectionNode implements RSyntaxNode, RSyntaxConstant { + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); + private ConstantNode(SourceSection sourceSection) { super(sourceSection); } @@ -59,15 +61,14 @@ public abstract class ConstantNode extends RSourceSectionNode implements RSyntax @Override public abstract Object getValue(); - @Override - public final Object execute(VirtualFrame frame) { - RContext.getInstance().setVisible(true); - return getValue(); + protected final void handleVisibility(VirtualFrame frame) { + visibility.execute(frame, true); } @Override - public void serializeImpl(RSerialize.State state) { - state.setCar(getValue()); + public final Object execute(VirtualFrame frame) { + handleVisibility(frame); + return getValue(); } public static ConstantNode create(Object value) { @@ -90,7 +91,7 @@ public abstract class ConstantNode extends RSourceSectionNode implements RSyntax // this can be created during argument matching and "call" return new ConstantObjectNode(sourceSection, value); } else { - assert value instanceof RTypedValue && !(value instanceof RPromise) : value; + assert value instanceof TruffleObject || value instanceof RTypedValue && !(value instanceof RPromise) : value; return new ConstantObjectNode(sourceSection, value); } } @@ -113,7 +114,7 @@ public abstract class ConstantNode extends RSourceSectionNode implements RSyntax @Override public double executeDouble(VirtualFrame frame) { - RContext.getInstance().setVisible(true); + handleVisibility(frame); return doubleValue; } } @@ -136,7 +137,7 @@ public abstract class ConstantNode extends RSourceSectionNode implements RSyntax @Override public byte executeByte(VirtualFrame frame) { - RContext.getInstance().setVisible(true); + handleVisibility(frame); return logicalValue; } } @@ -159,7 +160,7 @@ public abstract class ConstantNode extends RSourceSectionNode implements RSyntax @Override public int executeInteger(VirtualFrame frame) { - RContext.getInstance().setVisible(true); + handleVisibility(frame); return intValue; } } @@ -177,14 +178,5 @@ public abstract class ConstantNode extends RSourceSectionNode implements RSyntax public Object getValue() { return value; } - - @Override - public void serializeImpl(RSerialize.State state) { - if (value == RMissing.instance) { - state.setCar(RMissing.instance); - } else { - super.serializeImpl(state); - } - } } } 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 46ab6dc79f9f12af5c770c05d4dd1f2f2a07cfe9..3b81ac8dd520cf893191165f24f463bcbf1cbde1 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 @@ -22,19 +22,18 @@ */ package com.oracle.truffle.r.nodes.access; -import com.oracle.truffle.api.CompilerDirectives; 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; +import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode; +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.RType; -import com.oracle.truffle.r.runtime.context.RContext; +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; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; @@ -46,21 +45,23 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; public class ReadVariadicComponentNode extends RSourceSectionNode implements RSyntaxNode, RSyntaxLookup { @Child private ReadVariableNode lookup = ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any); - @Child private PromiseHelperNode promiseHelper; + @Child private PromiseCheckHelperNode promiseHelper = new PromiseCheckHelperNode(); + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); private final int index; + private final String name; private final BranchProfile errorBranch = BranchProfile.create(); - private final BranchProfile promiseBranch = BranchProfile.create(); public ReadVariadicComponentNode(SourceSection src, int index) { super(src); this.index = index; + this.name = Utils.intern(".." + Integer.toString(index + 1)); } @Override public Object execute(VirtualFrame frame) { - RContext.getInstance().setVisible(true); + visibility.execute(frame, true); Object args = lookup.execute(frame); if (args == null) { @@ -72,37 +73,21 @@ public class ReadVariadicComponentNode extends RSourceSectionNode implements RSy errorBranch.enter(); throw RError.error(this, RError.Message.NO_LIST_FOR_CDR); } - if (argsValuesAndNames.getLength() <= index) { errorBranch.enter(); throw RError.error(this, RError.Message.DOT_DOT_SHORT, index + 1); } Object ret = argsValuesAndNames.getArgument(index); - if (ret instanceof RPromise) { - promiseBranch.enter(); - // This might be the case, as lookup only checks for "..." to be a promise and forces it - // eventually, NOT (all) of its content - if (promiseHelper == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - promiseHelper = insert(new PromiseHelperNode()); - } - ret = promiseHelper.evaluate(frame, (RPromise) ret); - } - return ret == null ? RMissing.instance : ret; + return ret == null ? RMissing.instance : promiseHelper.checkEvaluate(frame, ret); } public String getPrintForm() { - return ".." + Integer.toString(index + 1); - } - - @Override - public void serializeImpl(com.oracle.truffle.r.runtime.RSerialize.State state) { - state.setCarAsSymbol(getPrintForm()); + return name; } @Override public String getIdentifier() { - return getPrintForm(); + return name; } @Override 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 28c07e510dce1781491d79502e3aefa728faa032..3a66dc1427fa8880bbf7e228ca667b1631edbb14 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 @@ -31,7 +31,6 @@ import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.access.RemoveAndAnswerNodeFactory.RemoveAndAnswerResolvedNodeGen; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RNode; @@ -103,7 +102,6 @@ public abstract class RemoveAndAnswerNode extends RNode { @Specialization(guards = "isObject(frame)") protected Object doObject(VirtualFrame frame) { - RContext.getInstance().setVisible(false); Object result; try { result = frame.getObject(slot); @@ -118,7 +116,6 @@ public abstract class RemoveAndAnswerNode extends RNode { @Specialization(guards = "isInt(frame)") protected int doInt(VirtualFrame frame) { - RContext.getInstance().setVisible(false); int result; try { result = frame.getInt(slot); @@ -133,7 +130,6 @@ public abstract class RemoveAndAnswerNode extends RNode { @Specialization(guards = "isDouble(frame)") protected double doDouble(VirtualFrame frame) { - RContext.getInstance().setVisible(false); double result; try { result = frame.getDouble(slot); @@ -148,7 +144,6 @@ public abstract class RemoveAndAnswerNode extends RNode { @Specialization(guards = "isByte(frame)") protected byte doByte(VirtualFrame frame) { - RContext.getInstance().setVisible(false); byte result; try { result = frame.getByte(slot); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteCurrentVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteCurrentVariableNode.java index f7dbb258511d99587e6636f7fad2ab9f7a927dc2..9875a1f006001499396499c88a86c7ae9217b148 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteCurrentVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteCurrentVariableNode.java @@ -26,9 +26,8 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RSerialize; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; @@ -40,16 +39,17 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; */ @NodeInfo(cost = NodeCost.NONE) public class WriteCurrentVariableNode extends WriteVariableNodeSyntaxHelper implements RSyntaxNode, RSyntaxCall { + @Child private WriteLocalFrameVariableNode writeLocalFrameVariableNode; + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); - protected WriteCurrentVariableNode(SourceSection src) { + protected WriteCurrentVariableNode(SourceSection src, String name, RNode rhs) { super(src); + writeLocalFrameVariableNode = WriteLocalFrameVariableNode.create(name, rhs, Mode.REGULAR); } static WriteCurrentVariableNode create(SourceSection src, String name, RNode rhs) { - WriteCurrentVariableNode result = new WriteCurrentVariableNode(src); - result.writeLocalFrameVariableNode = result.insert(WriteLocalFrameVariableNode.create(name, rhs, Mode.REGULAR)); - return result; + return new WriteCurrentVariableNode(src, name, rhs); } @Override @@ -65,7 +65,7 @@ public class WriteCurrentVariableNode extends WriteVariableNodeSyntaxHelper impl @Override public Object execute(VirtualFrame frame) { Object result = writeLocalFrameVariableNode.execute(frame); - RContext.getInstance().setVisible(false); + visibility.execute(frame, false); return result; } @@ -74,11 +74,6 @@ public class WriteCurrentVariableNode extends WriteVariableNodeSyntaxHelper impl writeLocalFrameVariableNode.execute(frame, value); } - @Override - public void serializeImpl(RSerialize.State state) { - serializeHelper(state, "<-"); - } - @Override public RSyntaxElement getSyntaxLHS() { return RSyntaxLookup.createDummyLookup(null, "<-", true); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperVariableNode.java index d79875a674117af26fed7c4b062dd65b1bc197bb..a58cbc56730d6dcfe3d9eb82e16ca9e26d8e6ebb 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperVariableNode.java @@ -26,9 +26,8 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RSerialize; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; @@ -47,15 +46,15 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; public class WriteSuperVariableNode extends WriteVariableNodeSyntaxHelper implements RSyntaxNode, RSyntaxCall { @Child private WriteVariableNode writeSuperFrameVariableNode; + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); - protected WriteSuperVariableNode(SourceSection src) { + protected WriteSuperVariableNode(SourceSection src, String name, RNode rhs) { super(src); + writeSuperFrameVariableNode = WriteSuperFrameVariableNode.create(name, rhs, Mode.REGULAR); } static WriteSuperVariableNode create(SourceSection src, String name, RNode rhs) { - WriteSuperVariableNode result = new WriteSuperVariableNode(src); - result.writeSuperFrameVariableNode = result.insert(WriteSuperFrameVariableNode.create(name, rhs, Mode.REGULAR)); - return result; + return new WriteSuperVariableNode(src, name, rhs); } @Override @@ -71,7 +70,7 @@ public class WriteSuperVariableNode extends WriteVariableNodeSyntaxHelper implem @Override public Object execute(VirtualFrame frame) { Object result = writeSuperFrameVariableNode.execute(frame); - RContext.getInstance().setVisible(false); + visibility.execute(frame, false); return result; } @@ -80,11 +79,6 @@ public class WriteSuperVariableNode extends WriteVariableNodeSyntaxHelper implem writeSuperFrameVariableNode.execute(frame, value); } - @Override - public void serializeImpl(RSerialize.State state) { - serializeHelper(state, "<<-"); - } - @Override public RSyntaxElement getSyntaxLHS() { return RSyntaxLookup.createDummyLookup(null, "<<-", true); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNodeSyntaxHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNodeSyntaxHelper.java index 27f7ff678e9d3d534c8643965c2311f7115c6ff7..c4f971adbcda4916979281c244805db4f243a535 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNodeSyntaxHelper.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNodeSyntaxHelper.java @@ -24,9 +24,6 @@ package com.oracle.truffle.r.nodes.access; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.source.SourceSection; -import com.oracle.truffle.r.runtime.RSerialize; -import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; -import com.oracle.truffle.r.runtime.nodes.RNode; abstract class WriteVariableNodeSyntaxHelper extends WriteVariableNode { @CompilationFinal private SourceSection sourceSectionR; @@ -36,21 +33,6 @@ abstract class WriteVariableNodeSyntaxHelper extends WriteVariableNode { this.sourceSectionR = sourceSection; } - protected void serializeHelper(RSerialize.State state, String op) { - RNode rhs = getRhs(); - if (rhs == null) { - state.setCarAsSymbol(getName().toString()); - } else { - state.setAsBuiltin(op); - state.openPairList(SEXPTYPE.LISTSXP); - state.setCarAsSymbol(getName().toString()); - state.openPairList(SEXPTYPE.LISTSXP); - state.serializeNodeSetCar(getRhs()); - state.linkPairList(2); - state.setCdr(state.closePairList()); - } - } - public void setSourceSection(SourceSection sourceSection) { this.sourceSectionR = sourceSection; } 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 af81aeda0554f914891be7367e96c96aed66ef5f..467979baa851fa9944e5bd5a08893ab06b317d96 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 @@ -31,6 +31,7 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; 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.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameSlot; @@ -47,22 +48,22 @@ 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.function.PromiseHelperNode; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.FastROptions; 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.RSerialize; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.StableValue; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RFunction; 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.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; @@ -128,6 +129,8 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta @Child private PromiseHelperNode promiseHelper; @Child private CheckTypeNode checkTypeNode; + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); + @CompilationFinal private FrameLevel read; @CompilationFinal private boolean needsCopying; @@ -163,11 +166,6 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta return mode; } - @Override - public void serializeImpl(RSerialize.State state) { - state.setCarAsSymbol(identifierAsString); - } - @Override public boolean isSyntax() { return identifier instanceof String; @@ -185,7 +183,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta private Object executeInternal(VirtualFrame frame, Frame variableFrame) { if (kind != ReadKind.Silent) { - RContext.getInstance().setVisible(true); + visibility.execute(frame, true); } Object result; @@ -305,6 +303,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta private final FrameSlot slot; private final ConditionProfile isNullProfile = ConditionProfile.createBinaryProfile(); private final ValueProfile frameProfile = ValueProfile.createClassProfile(); + private final ValueProfile valueProfile = ValueProfile.createClassProfile(); private Match(FrameSlot slot) { this.slot = slot; @@ -316,7 +315,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta if (!checkType(frame, value, isNullProfile)) { throw new LayoutChangedException(); } - return value; + return valueProfile.profile(value); } @Override @@ -885,6 +884,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta /* * This is RRuntime.checkType in the node form. */ +@TypeSystemReference(RTypes.class) abstract class CheckTypeNode extends RBaseNode { public abstract boolean executeBoolean(Object o); @@ -926,12 +926,17 @@ abstract class CheckTypeNode extends RBaseNode { return type == RType.Function || type == RType.Closure || type == RType.Builtin || type == RType.Special; } + @Specialization(guards = "isExternalObject(o)") + boolean checkType(@SuppressWarnings("unused") TruffleObject o) { + return type == RType.Function || type == RType.Closure || type == RType.Builtin || type == RType.Special; + } + + protected static boolean isExternalObject(TruffleObject o) { + return !(o instanceof RTypedValue); + } + @Fallback - boolean checkType(Object o) { - if (type == RType.Function || type == RType.Closure || type == RType.Builtin || type == RType.Special) { - return o instanceof TruffleObject && !(o instanceof RTypedValue); - } else { - return false; - } + boolean checkType(@SuppressWarnings("unused") Object o) { + return false; } } 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 b413695e4e66158d896515e37aa00507de4c4367..1c62578267bd856845c1ac5fd597a82b8ac5eb21 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 @@ -28,7 +28,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; 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.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.access.vector.CachedExtractVectorNodeFactory.SetNamesNodeGen; @@ -42,7 +41,6 @@ import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RAttributes; 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.RList; import com.oracle.truffle.r.runtime.data.RLogical; @@ -99,7 +97,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { this.dropDimensions = logicalAsBoolean(dropDimensions, DEFAULT_DROP_DIMENSION); this.positionsCheckNode = new PositionsCheckNode(mode, vectorType, convertedPositions, this.exact, false, recursive); if (error == null && vectorType != RType.Null && vectorType != RType.Environment) { - this.writeVectorNode = WriteIndexedVectorNode.create(vectorType, convertedPositions.length, true, false, false); + this.writeVectorNode = WriteIndexedVectorNode.create(vectorType, convertedPositions.length, true, false, false, false); } } @@ -162,10 +160,12 @@ final class CachedExtractVectorNode extends CachedVectorNode { } int extractedVectorLength = positionsCheckNode.getSelectedPositionsCount(positionProfiles); - final RVector extractedVector; + final RVector<?> extractedVector; switch (vectorType) { - case Language: case Expression: + extractedVector = RType.Expression.create(extractedVectorLength, false); + break; + case Language: case PairList: extractedVector = RType.List.create(extractedVectorLength, false); break; @@ -195,7 +195,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { switch (vectorType) { case Expression: - return new RExpression((RList) extractedVector); + return extractedVector; case Language: return materializeLanguage(extractedVector); default: @@ -274,9 +274,11 @@ final class CachedExtractVectorNode extends CachedVectorNode { private final ConditionProfile dimNamesNull = ConditionProfile.createBinaryProfile(); private final ValueProfile foundDimNamesProfile = ValueProfile.createClassProfile(); private final ConditionProfile selectPositionsProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile originalDimNamesPRofile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile foundNamesProfile = ConditionProfile.createBinaryProfile(); @ExplodeLoop - private void applyDimensions(RAbstractContainer originalTarget, RVector extractedTarget, int extractedTargetLength, PositionProfile[] positionProfile, Object[] positions) { + private void applyDimensions(RAbstractContainer originalTarget, RVector<?> extractedTarget, int extractedTargetLength, PositionProfile[] positionProfile, Object[] positions) { // TODO speculate on the number of counted dimensions int dimCount = countDimensions(positionProfile); @@ -311,9 +313,9 @@ final class CachedExtractVectorNode extends CachedVectorNode { if (newDimNames != null) { extractedTarget.setDimNames(RDataFactory.createList(newDimNames)); } - } else if (newDimNames != null && originalDimNames.getLength() > 0) { + } else if (newDimNames != null && originalDimNamesPRofile.profile(originalDimNames.getLength() > 0)) { RAbstractStringVector foundNames = translateDimNamesToNames(positionProfile, originalDimNames, extractedTargetLength, positions); - if (foundNames != null) { + if (foundNamesProfile.profile(foundNames != null)) { foundNames = foundDimNamesProfile.profile(foundNames); if (foundNames.getLength() > 0) { metadataApplied.enter(); @@ -323,7 +325,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { } } - private final BranchProfile droppedDimensionProfile = BranchProfile.create(); + private final ConditionProfile droppedDimensionProfile = ConditionProfile.createBinaryProfile(); @ExplodeLoop private int countDimensions(PositionProfile[] boundsProfile) { @@ -331,8 +333,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { int dimCount = numberOfDimensions; for (int i = 0; i < numberOfDimensions; i++) { int selectedPositionsCount = boundsProfile[i].selectedPositionsCount; - if (selectedPositionsCount == 1) { - droppedDimensionProfile.enter(); + if (droppedDimensionProfile.profile(selectedPositionsCount == 1)) { dimCount--; } } @@ -342,6 +343,8 @@ final class CachedExtractVectorNode extends CachedVectorNode { } } + private final ConditionProfile srcNamesProfile = ConditionProfile.createBinaryProfile(); + private final ValueProfile srcNamesValueProfile = ValueProfile.createClassProfile(); private final ConditionProfile newNamesProfile = ConditionProfile.createBinaryProfile(); @ExplodeLoop @@ -353,8 +356,8 @@ final class CachedExtractVectorNode extends CachedVectorNode { continue; } - Object srcNames = originalDimNames.getDataAt(currentDimIndex); - if (srcNames != RNull.instance) { + Object srcNames = srcNamesValueProfile.profile(originalDimNames.getDataAt(currentDimIndex)); + if (srcNamesProfile.profile(srcNames != RNull.instance)) { Object position = positions[currentDimIndex]; Object newNames = extractNames((RAbstractStringVector) RRuntime.asAbstractVector(srcNames), new Object[]{position}, new PositionProfile[]{profile}, currentDimIndex, @@ -403,7 +406,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { } } - private void setNames(RVector vector, Object newNames) { + private void setNames(RVector<?> vector, Object newNames) { if (setNamesNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); setNamesNode = insert(SetNamesNodeGen.create()); @@ -413,10 +416,10 @@ final class CachedExtractVectorNode extends CachedVectorNode { protected abstract static class SetNamesNode extends Node { - public abstract void execute(RVector container, Object newNames); + public abstract void execute(RVector<?> container, Object newNames); @Specialization - protected void setNames(RVector container, RAbstractStringVector newNames) { + protected void setNames(RVector<?> container, RAbstractStringVector newNames) { RStringVector newNames1 = newNames.materialize(); assert newNames1.getLength() <= container.getLength(); assert container.getInternalDimensions() == null; @@ -435,13 +438,13 @@ final class CachedExtractVectorNode extends CachedVectorNode { } @Specialization - protected void setNames(RVector container, String newNames) { + protected void setNames(RVector<?> container, String newNames) { // TODO: why materialize()? setNames(container, RString.valueOf(newNames).materialize()); } @Specialization - protected void setNames(RVector container, @SuppressWarnings("unused") RNull newNames) { + protected void setNames(RVector<?> container, @SuppressWarnings("unused") RNull newNames) { assert container.getAttributes() == null; } } 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 88bbd03245bbbc485a22a0394c04c525e3c5ad63..5cfa7d0fd7044fb240eed4b22305d51bff2c6664 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 @@ -44,7 +44,6 @@ import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RAttributes; 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.RList; import com.oracle.truffle.r.runtime.data.RMissing; @@ -74,7 +73,6 @@ final class CachedReplaceVectorNode extends CachedVectorNode { private final BranchProfile warningBranch = BranchProfile.create(); private final RAttributeProfiles vectorNamesProfile = RAttributeProfiles.create(); private final RAttributeProfiles positionNamesProfile = RAttributeProfiles.create(); - private final ConditionProfile rightIsShared = ConditionProfile.createBinaryProfile(); private final ConditionProfile valueIsNA = ConditionProfile.createBinaryProfile(); private final BranchProfile resizeProfile = BranchProfile.create(); private final BranchProfile sharedProfile = BranchProfile.create(); @@ -114,7 +112,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode { Object[] convertedPositions = filterPositions(positions); this.positionsCheckNode = new PositionsCheckNode(mode, vectorType, convertedPositions, true, true, recursive); if (castType != null && !castType.isNull()) { - this.writeVectorNode = WriteIndexedVectorNode.create(castType, convertedPositions.length, false, true, mode.isSubscript() && !isDeleteElements()); + this.writeVectorNode = WriteIndexedVectorNode.create(castType, convertedPositions.length, false, true, mode.isSubscript() && !isDeleteElements(), true); } } @@ -194,9 +192,6 @@ final class CachedReplaceVectorNode extends CachedVectorNode { vector.initAttributes(attrs.copy()); } break; - case Expression: - vector = ((RExpression) castVector).getList(); - break; default: vector = (RAbstractVector) castVector; break; @@ -221,18 +216,18 @@ final class CachedReplaceVectorNode extends CachedVectorNode { int replacementLength = positionsCheckNode.getSelectedPositionsCount(positionProfiles); if (emptyReplacementProfile.profile(replacementLength == 0)) { /* Nothing to modify */ - return vector.materialize(); + if (vectorType == RType.Language || vectorType == RType.Expression) { + return originalVector; + } else { + return vector.materialize(); + } } if (valueLengthOneProfile.profile(valueLength != 1)) { verifyValueLength(positionProfiles, valueLength); } - if (isList()) { - if (mode.isSubscript()) { - value = copyValueOnAssignment(value); - } - } else if (value instanceof RAbstractVector) { + if (!isList() && value instanceof RAbstractVector) { value = ((RAbstractVector) value).castSafe(castType, valueIsNA); } @@ -245,16 +240,21 @@ final class CachedReplaceVectorNode extends CachedVectorNode { return wrapResult(vector, repType); } vector = resizeVector(vector, maxOutOfBounds); + } else { + vector = vector.materialize(); } - vector = vector.materialize(); - if (originalVector != vector && vector instanceof RShareable) { - RShareable shareable = (RShareable) vector; - // we created a new object, and this needs to be non-temporary - if (shareable.isTemporary()) { - shareable.incRefCount(); - } - } + // Note: the refCount of elements inside lists can stay the same. If we are replacing in a + // what was originally shared list, we made a shallow copy of it, but all its elements must + // be in shared state already anyway. If we are replacing in non-shared list and we just + // threw it away to replace it with larger one, the elements are in non-shared or temporary + // state, which is again OK. + // + // The refcount of the list/vector itself: if the write node in "v <- `$<-`(...)" sees that + // we are assigning the same object that 'v' already contains, it is going to skip the + // assignment and skip the refCount increment. If we created a new object by + // resizing/materializing 'vector', it will be marked as 'temporary' and its refCount + // incremented during the assignment step. vectorLength = targetLengthProfile.profile(vector.getLength()); @@ -488,7 +488,6 @@ final class CachedReplaceVectorNode extends CachedVectorNode { shareable = (RShareable) returnVector.copy(); returnVector = (RAbstractVector) shareable; assert shareable.isTemporary(); - shareable.incRefCount(); } } returnVector = sharedClassProfile.profile(returnVector); @@ -498,21 +497,6 @@ final class CachedReplaceVectorNode extends CachedVectorNode { return returnVector; } - private final ConditionProfile rightIsNotTemporary = ConditionProfile.createBinaryProfile(); - - private RTypedValue copyValueOnAssignment(RTypedValue value) { - if (value instanceof RShareable && value instanceof RAbstractVector) { - RShareable val = (RShareable) value; - if (rightIsShared.profile(val.isShared())) { - val = val.copy(); - } else if (rightIsNotTemporary.profile(!val.isTemporary())) { - val.incRefCount(); - } - return val; - } - return value; - } - // TODO (chumer) this is way to compilicated at the moment // not yet worth compiling. we should introduce some nodes for this @TruffleBoundary @@ -523,9 +507,9 @@ final class CachedReplaceVectorNode extends CachedVectorNode { // TODO (chumer) this is way to complicated at the moment // its not yet worth compiling it we need a better attribute system @TruffleBoundary - private RVector resizeVector(RAbstractVector vector, int size) { + private RVector<?> resizeVector(RAbstractVector vector, int size) { RStringVector oldNames = vector.getNames(vectorNamesProfile); - RVector res = vector.copyResized(size, true).materialize(); + RVector<?> res = vector.copyResized(size, true).materialize(); if (vector instanceof RVector) { res.copyAttributesFrom(positionNamesProfile, vector); } @@ -538,8 +522,11 @@ final class CachedReplaceVectorNode extends CachedVectorNode { return res; } + private final ConditionProfile updateNamesProfile = ConditionProfile.createBinaryProfile(); + private void updatePositionNames(RAbstractVector resultVector, RAbstractStringVector positionNames, Object[] positions) { - RTypedValue names = resultVector.getNames(positionNamesProfile); + RTypedValue originalNames = resultVector.getNames(positionNamesProfile); + RTypedValue names = originalNames; if (names == null) { String[] emptyVector = new String[resultVector.getLength()]; Arrays.fill(emptyVector, ""); @@ -551,7 +538,9 @@ final class CachedReplaceVectorNode extends CachedVectorNode { } assert copyPositionNames.isSupported(names, positions, positionNames); RAbstractStringVector newNames = (RAbstractStringVector) copyPositionNames.apply(names, positions, positionNames); - resultVector.setNames(newNames.materialize()); + if (updateNamesProfile.profile(newNames != originalNames)) { + resultVector.setNames(newNames.materialize()); + } } private static final class DeleteElementsNode extends Node { 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 new file mode 100644 index 0000000000000000000000000000000000000000..6ecdd95d18dbd4e533d7a1e20b05aa0a4d2518c6 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java @@ -0,0 +1,129 @@ +/* + * 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.access.vector; + +import com.oracle.truffle.api.dsl.Cached; +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.nodes.access.vector.ExtractListElementNodeGen.UpdateStateOfListElementNodeGen; +import com.oracle.truffle.r.runtime.data.RListBase; +import com.oracle.truffle.r.runtime.data.RShareable; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +/** + * Internal node that extracts data under given index from any RAbstractContainer. In the case of + * RListBase, it also invokes {@link UpdateStateOfListElement} on the element before returning it. + * + * There are two reasons for why one accesses an element of a list: to peek at it, possibly + * calculate some values from it, and then forget it. In such case, it is OK to access the element + * directly through {@link RAbstractListVector#getDataAt(int)} or + * {@link RAbstractContainer#getDataAtAsObject(int)}. However, if the object is going to be returned + * to the user either as return value of a built-in, put inside a list, put as an attribute, or its + * true reference count matters for some other reason, then its reference count must be put into a + * consistent state, which is done by {@link UpdateStateOfListElement}. This node is a convenient + * wrapper that performs the extraction as well as invocation of {@link UpdateStateOfListElement}. + * See also the documentation of {@link RListBase}. + */ +public abstract class ExtractListElement extends Node { + + public abstract Object execute(RAbstractContainer container, int index); + + public static ExtractListElement create() { + return ExtractListElementNodeGen.create(); + } + + @Specialization + protected Object doList(RListBase list, int index, @Cached("create()") UpdateStateOfListElement updateStateNode) { + Object element = list.getDataAt(index); + return updateStateNode.updateState(list, element); + } + + @Specialization(guards = "isNotList(container)") + protected Object doOthers(RAbstractContainer container, int index) { + return container.getDataAtAsObject(index); + } + + protected static boolean isNotList(RAbstractContainer x) { + return !(x instanceof RAbstractListVector); + } + + public abstract static class UpdateStateOfListElement extends Node { + + public abstract void execute(Object owner, Object item); + + /** + * Provides more convenient interface for the {@link #execute(Object, Object)} method. + */ + public final <T> T updateState(RAbstractContainer owner, T item) { + execute(owner, item); + return item; + } + + public static UpdateStateOfListElement create() { + return UpdateStateOfListElementNodeGen.create(); + } + + @Specialization + protected void doShareableValues(RListBase owner, RShareable value, + @Cached("createClassProfile()") ValueProfile valueProfile, + @Cached("createBinaryProfile()") ConditionProfile sharedValue, + @Cached("createBinaryProfile()") ConditionProfile temporaryOwner) { + RShareable profiledValue = valueProfile.profile(value); + if (sharedValue.profile(profiledValue.isShared())) { + // it is already shared, not need to do anything + return; + } + + 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 + // to transition the element, it may stay temporary. + return; + } + + if (profiledValue.isTemporary()) { + // make it at least non-shared (parent list must be also at least non-shared) + profiledValue.incRefCount(); + } + if (owner.isShared()) { + // owner is shared, make the value shared too + profiledValue.incRefCount(); + } + } + + @Specialization(guards = "isFallback(owner, value)") + protected void doFallback(Object owner, Object value) { + assert !(value instanceof RShareable && owner instanceof RAbstractVector && !(owner instanceof RListBase)) : "RShareables can only live inside lists and no other vectors."; + // nop: either value is not RShareable, or the owner is "list" like structure with + // reference semantics (e.g. REnvironment) + } + + protected static boolean isFallback(Object owner, Object value) { + return !(value instanceof RShareable) || !(owner instanceof RListBase); + } + } +} 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 22812156efd82ae05301d1810c8419664093ae27..c86bb8ea230a03ad1f112810f5d7e49f4635329a 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 @@ -135,13 +135,13 @@ public abstract class ExtractVectorNode extends Node { } @Specialization(guards = {"cached != null", "cached.isSupported(vector, positions)"}) - protected Object doReplaceSameDimensions(VirtualFrame frame, RAbstractVector vector, Object[] positions, Object exact, Object dropDimensions, // + protected Object doExtractSameDimensions(VirtualFrame frame, RAbstractVector vector, Object[] positions, Object exact, Object dropDimensions, // @Cached("createRecursiveCache(vector, positions)") RecursiveExtractSubscriptNode cached) { return cached.apply(frame, vector, positions, exact, dropDimensions); } @Specialization(guards = {"cached != null", "cached.isSupported(vector, positions)"}) - protected Object doReplaceRecursive(VirtualFrame frame, RAbstractListVector vector, Object[] positions, Object exact, Object dropDimensions, // + protected Object doExtractRecursive(VirtualFrame frame, RAbstractListVector vector, Object[] positions, Object exact, Object dropDimensions, // @Cached("createRecursiveCache(vector, positions)") RecursiveExtractSubscriptNode cached) { return cached.apply(frame, vector, positions, exact, dropDimensions); } @@ -158,7 +158,7 @@ public abstract class ExtractVectorNode extends Node { } @Specialization(limit = "CACHE_LIMIT", guards = {"cached != null", "cached.isSupported(vector, positions, exact, dropDimensions)"}) - protected Object doReplaceDefaultCached(Object vector, Object[] positions, Object exact, Object dropDimensions, // + protected Object doExtractDefaultCached(Object vector, Object[] positions, Object exact, Object dropDimensions, // @Cached("createDefaultCache(getThis(), vector, positions, exact, dropDimensions)") CachedExtractVectorNode cached) { assert !isRecursiveSubscript(vector, positions); return cached.apply(vector, positions, null, exact, dropDimensions); @@ -168,9 +168,9 @@ public abstract class ExtractVectorNode extends Node { return new CachedExtractVectorNode(node.getMode(), (RTypedValue) vector, positions, (RTypedValue) exact, (RTypedValue) dropDimensions, node.recursive); } - @Specialization(contains = "doReplaceDefaultCached") + @Specialization(contains = "doExtractDefaultCached") @TruffleBoundary - protected Object doReplaceDefaultGeneric(Object vector, Object[] positions, Object exact, Object dropDimensions, // + protected Object doExtractDefaultGeneric(Object vector, Object[] positions, Object exact, Object dropDimensions, // @Cached("new(createDefaultCache(getThis(), vector, positions, exact, dropDimensions))") GenericVectorExtractNode generic) { return generic.get(this, vector, positions, exact, dropDimensions).apply(vector, positions, null, exact, dropDimensions); } @@ -196,5 +196,4 @@ public abstract class ExtractVectorNode extends Node { return cached; } } - } 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 2b934346531f514f596a3e9dd7acc73b30cc4073..e437eef25787fc36433b988c3109a99dcd04ba6b 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 @@ -61,15 +61,14 @@ final class PositionCharacterLookupNode extends Node { emptyProfile.enter(); names = RDataFactory.createEmptyStringVector(); } - result = searchNode.apply(names, position, notFoundStartIndex); - result.setNames(position.materialize()); + result = searchNode.apply(names, position, notFoundStartIndex, position.materialize()); } else { RList dimNames = target.getDimNames(attributeProfiles); if (dimNames != null) { Object dataAt = dimNames.getDataAt(dimensionIndex); if (dataAt != RNull.instance) { RStringVector dimName = (RStringVector) dataAt; - result = searchNode.apply(dimName, position, notFoundStartIndex); + result = searchNode.apply(dimName, position, notFoundStartIndex, null); } else { emptyProfile.enter(); 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 6b866e9f8b45ab1140e73735d36dc32248d85a7d..bc29b18d2a136d3ebb10508126a66727b3b771a0 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.access.vector; import java.util.Arrays; +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; @@ -37,6 +38,7 @@ import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; 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.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; @@ -244,12 +246,12 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode { } } } - return doIntegerProfiled(profile, dimensionLength, position, positionLength, seenPositiveFlagProfile.profile(hasSeenPositive), seenNegativeFlagProfile.profile(hasSeenNegative), seenNAFlagProfile.profile(hasSeenNA), outOfBoundsCount, zeroCount, maxOutOfBoundsIndex); } private final BranchProfile noZeroes = BranchProfile.create(); + 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) { @@ -283,6 +285,14 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode { } private RAbstractVector eliminateZerosAndOutOfBounds(RAbstractIntVector position, int positionLength, int dimensionLength, int outOfBoundsCount, int zeroCount, boolean hasSeenNA) { + if (checkForScalarPosition) { + if (position instanceof RInteger && outOfBoundsCount == 1) { + return RInteger.valueOf(RRuntime.INT_NA); + } else { + CompilerDirectives.transferToInterpreterAndInvalidate(); + checkForScalarPosition = false; + } + } int[] newIndices = new int[positionLength - zeroCount]; int newPositionIndex = 0; for (int i = 0; i < positionLength; i++) { 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 c83e56efcc76dd8284a1139f085bf9acf6bece68..3ab96e71be61213a05440038eba694b6d25bac6b 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 @@ -44,6 +44,7 @@ final class PositionsCheckNode extends Node { private final VectorLengthProfile selectedPositionsCountProfile = VectorLengthProfile.create(); private final VectorLengthProfile maxOutOfBoundsProfile = VectorLengthProfile.create(); private final ConditionProfile containsNAProfile = ConditionProfile.createBinaryProfile(); + private final BranchProfile unsupportedProfile = BranchProfile.create(); private final boolean replace; private final int positionsLength; @@ -64,10 +65,12 @@ final class PositionsCheckNode extends Node { @ExplodeLoop public boolean isSupported(Object[] positions) { if (positionsCheck.length != positions.length) { + unsupportedProfile.enter(); return false; } for (int i = 0; i < positionsCheck.length; i++) { if (!positionsCheck[i].isSupported(positions[i])) { + unsupportedProfile.enter(); return false; } } 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 f8957c71776a168ff2b5d7c94bf001b80d086989..5fc03e937e0d3d1a82a0ed368d9f92bec13c6bcf 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 @@ -110,15 +110,19 @@ public abstract class ReplaceVectorNode extends Node { } Object position = positions[0]; try { - if (position instanceof String || position instanceof Double || position instanceof Integer) { + if (position instanceof Integer) { + return ForeignAccess.send(foreignRead, frame, object, new Object[]{((Integer) position) - 1, writtenValue}); + } else if (position instanceof Double) { + return ForeignAccess.send(foreignRead, frame, object, new Object[]{((Double) position) - 1, writtenValue}); + } else if (position instanceof String) { return ForeignAccess.send(foreignRead, frame, object, new Object[]{position, writtenValue}); } else if (position instanceof RAbstractStringVector) { String string = firstString.executeString(castNode.execute(position)); return ForeignAccess.send(foreignRead, frame, object, new Object[]{string, writtenValue}); } else if (position instanceof RAbstractDoubleVector) { - return ForeignAccess.send(foreignRead, frame, object, new Object[]{((RAbstractDoubleVector) position).getDataAt(0), writtenValue}); + return ForeignAccess.send(foreignRead, frame, object, new Object[]{((RAbstractDoubleVector) position).getDataAt(0) - 1, writtenValue}); } else if (position instanceof RAbstractIntVector) { - return ForeignAccess.send(foreignRead, frame, object, new Object[]{((RAbstractIntVector) position).getDataAt(0), writtenValue}); + return ForeignAccess.send(foreignRead, frame, object, new Object[]{((RAbstractIntVector) position).getDataAt(0) - 1, writtenValue}); } else { throw RError.error(this, RError.Message.GENERIC, "invalid index during foreign access"); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/SearchFirstStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/SearchFirstStringNode.java index 5980433725bf6bfee1b74e7310e801be0a8310f0..751a795d6d42723765e7b01c9a52ff8bad2de5e1 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/SearchFirstStringNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/SearchFirstStringNode.java @@ -32,6 +32,7 @@ import com.oracle.truffle.r.nodes.access.vector.SearchFirstStringNode.CompareStr import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; import com.oracle.truffle.r.runtime.RRuntime; 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; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -72,7 +73,7 @@ final class SearchFirstStringNode extends Node { } } - public RAbstractIntVector apply(RAbstractStringVector target, RAbstractStringVector elements, int notFoundStartIndex) { + public RAbstractIntVector apply(RAbstractStringVector target, RAbstractStringVector elements, int notFoundStartIndex, RStringVector names) { RAbstractStringVector targetProfiled = targetClassProfile.profile(target); RAbstractStringVector elementsProfiled = elementsClassProfile.profile(elements); @@ -84,7 +85,7 @@ final class SearchFirstStringNode extends Node { if (cachedIndices == UNINTIALIZED_CACHED_INDICES) { CompilerDirectives.transferToInterpreterAndInvalidate(); - cachedIndices = searchCached(targetProfiled, targetLength, elementsProfiled, elementsLength); + cachedIndices = searchCached(targetProfiled, targetLength, elementsProfiled, elementsLength, names); } if (cachedIndices != null) { if (!isCacheValid(targetProfiled, targetLength, elementsProfiled, elementsLength, cachedIndices)) { @@ -92,21 +93,21 @@ final class SearchFirstStringNode extends Node { cachedIndices = null; // set to generic // fallthrough to generic } else { - assert sameVector(searchCached(target, targetLength, elements, elementsLength), cachedIndices); - return RDataFactory.createIntVector(cachedIndices, true); + assert sameVector(searchCached(target, targetLength, elements, elementsLength, names), cachedIndices); + return RDataFactory.createIntVector(cachedIndices, true, names); } } - return searchGeneric(targetProfiled, targetLength, elementsProfiled, elementsLength, notFoundStartIndex, false); + return searchGeneric(targetProfiled, targetLength, elementsProfiled, elementsLength, notFoundStartIndex, false, names); } public static SearchFirstStringNode createNode(boolean exactMatch, boolean useNAForNotFound) { return new SearchFirstStringNode(exactMatch, useNAForNotFound); } - private int[] searchCached(RAbstractStringVector target, int targetLength, RAbstractStringVector elements, int elementsLength) { + private int[] searchCached(RAbstractStringVector target, int targetLength, RAbstractStringVector elements, int elementsLength, RStringVector names) { if (exactMatch) { - RAbstractIntVector genericResult = searchGeneric(target, targetLength, elements, elementsLength, -1, true); + RAbstractIntVector genericResult = searchGeneric(target, targetLength, elements, elementsLength, -1, true, names); if (genericResult != null) { return (int[]) genericResult.getInternalStore(); } @@ -170,7 +171,8 @@ final class SearchFirstStringNode extends Node { private final BranchProfile notFoundProfile = BranchProfile.create(); - private RAbstractIntVector searchGeneric(RAbstractStringVector target, int targetLength, RAbstractStringVector elements, int elementsLength, int notFoundStartIndex, boolean nullOnNotFound) { + private RAbstractIntVector searchGeneric(RAbstractStringVector target, int targetLength, RAbstractStringVector elements, int elementsLength, int notFoundStartIndex, boolean nullOnNotFound, + RStringVector names) { int notFoundIndex = notFoundStartIndex; int[] indices = new int[elementsLength]; boolean resultComplete = true; @@ -207,7 +209,7 @@ final class SearchFirstStringNode extends Node { } } - return RDataFactory.createIntVector(indices, resultComplete && elements.isComplete()); + return RDataFactory.createIntVector(indices, resultComplete && elements.isComplete(), names); } private int findIndex(RAbstractStringVector target, int targetLength, String element) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/WriteIndexedVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/WriteIndexedVectorNode.java index a8b664222674a50e93b3911bf3a261ee40e29ed8..b96380cab8e9f6aa985faee814e5818c88a57986 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/WriteIndexedVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/WriteIndexedVectorNode.java @@ -32,6 +32,8 @@ import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.LoopConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.nodes.access.vector.ExtractListElement.UpdateStateOfListElement; +import com.oracle.truffle.r.nodes.function.opt.ShareObjectNode; import com.oracle.truffle.r.nodes.profile.AlwaysOnBranchProfile; import com.oracle.truffle.r.nodes.profile.IntValueProfile; import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; @@ -48,7 +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.RAbstractListBaseVector; 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; @@ -87,19 +89,19 @@ abstract class WriteIndexedVectorNode extends Node { @Child private WriteIndexedVectorNode innerVectorNode; @SuppressWarnings("unchecked") - protected WriteIndexedVectorNode(RType vectorType, int totalDimensions, int dimensionIndex, boolean positionAppliesToRight, boolean skipNA, boolean setListElementAsObject) { - this.scalarNode = (WriteIndexedScalarNode<RAbstractVector, RTypedValue>) createIndexedAction(vectorType, setListElementAsObject); + protected WriteIndexedVectorNode(RType vectorType, int totalDimensions, int dimensionIndex, boolean positionAppliesToRight, boolean skipNA, boolean setListElementAsObject, boolean isReplace) { + this.scalarNode = (WriteIndexedScalarNode<RAbstractVector, RTypedValue>) createIndexedAction(vectorType, setListElementAsObject, isReplace); this.dimensionIndex = dimensionIndex; this.totalDimensions = totalDimensions; this.positionsApplyToRight = positionAppliesToRight; this.skipNA = skipNA; if (dimensionIndex > 0) { - innerVectorNode = WriteIndexedVectorNodeGen.create(vectorType, totalDimensions, dimensionIndex - 1, positionAppliesToRight, skipNA, setListElementAsObject); + innerVectorNode = WriteIndexedVectorNodeGen.create(vectorType, totalDimensions, dimensionIndex - 1, positionAppliesToRight, skipNA, setListElementAsObject, isReplace); } } - public static WriteIndexedVectorNode create(RType vectorType, int totalDimensions, boolean positionAppliesToValue, boolean skipNA, boolean setListElementAsObject) { - return WriteIndexedVectorNodeGen.create(vectorType, totalDimensions, totalDimensions - 1, positionAppliesToValue, skipNA, setListElementAsObject); + public static WriteIndexedVectorNode create(RType vectorType, int totalDimensions, boolean positionAppliesToValue, boolean skipNA, boolean setListElementAsObject, boolean isReplace) { + return WriteIndexedVectorNodeGen.create(vectorType, totalDimensions, totalDimensions - 1, positionAppliesToValue, skipNA, setListElementAsObject, isReplace); } public NACheck getValueNACheck() { @@ -375,7 +377,7 @@ abstract class WriteIndexedVectorNode extends Node { } } - private static WriteIndexedScalarNode<? extends RAbstractVector, ? extends RTypedValue> createIndexedAction(RType type, boolean setListElementAsObject) { + private static WriteIndexedScalarNode<? extends RAbstractVector, ? extends RTypedValue> createIndexedAction(RType type, boolean setListElementAsObject, boolean isReplace) { switch (type) { case Logical: return new WriteLogicalAction(); @@ -393,7 +395,7 @@ abstract class WriteIndexedVectorNode extends Node { case Expression: case PairList: case List: - return new WriteListAction(setListElementAsObject); + return new WriteListAction(setListElementAsObject, isReplace); default: throw RInternalError.shouldNotReachHere(); } @@ -467,16 +469,25 @@ abstract class WriteIndexedVectorNode extends Node { } } - private static final class WriteListAction extends WriteIndexedScalarNode<RAbstractListVector, RTypedValue> { + private static final class WriteListAction extends WriteIndexedScalarNode<RAbstractListBaseVector, RTypedValue> { private final boolean setListElementAsObject; + private final boolean isReplace; + @Child private UpdateStateOfListElement updateStateOfListElement; + @Child private ShareObjectNode shareObjectNode; - WriteListAction(boolean setListElementAsObject) { + WriteListAction(boolean setListElementAsObject, boolean isReplace) { this.setListElementAsObject = setListElementAsObject; + this.isReplace = isReplace; + if (!isReplace) { + updateStateOfListElement = UpdateStateOfListElement.create(); + } else { + shareObjectNode = ShareObjectNode.create(); + } } @Override - void apply(RAbstractListVector leftAccess, Object leftStore, int leftIndex, RTypedValue rightAccess, Object rightStore, int rightIndex) { + void apply(RAbstractListBaseVector leftAccess, Object leftStore, int leftIndex, RTypedValue rightAccess, Object rightStore, int rightIndex) { Object rightValue; if (setListElementAsObject) { rightValue = rightAccess; @@ -488,6 +499,16 @@ abstract class WriteIndexedVectorNode extends Node { rightValue = ((RAbstractContainer) rightAccess).getDataAtAsObject(rightStore, rightIndex); } + if (isReplace) { + // we are replacing within the same list + if (leftAccess.getDataAtAsObject(leftStore, leftIndex) != rightValue) { + shareObjectNode.execute(rightValue); + } + } else { + // we are writing into a list data that are being read from possibly another list + updateStateOfListElement.execute(rightAccess, rightValue); + } + leftAccess.setDataAt(leftStore, leftIndex, rightValue); valueNACheck.checkListElement(rightValue); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccess.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccess.java index eff4b0c6e2f5e882b6d44441c7f6c68af3d5017c..d895f4b7aaf70b576440916d85c1aa537dea00af 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccess.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccess.java @@ -29,22 +29,23 @@ 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.r.runtime.Utils; import com.oracle.truffle.r.runtime.data.RAttributes; import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** - * Simple attribute access node that specializes on the position at which the attribute was found - * last time. + * Simple attribute access node, for a specific attributes, that specializes on the position at + * which the attribute was found last time. */ public abstract class AttributeAccess extends RBaseNode { - private static final int MAX_SIZE_BOUND = 10; + public static final int MAX_SIZE_BOUND = 10; protected final String name; @CompilationFinal private int maximumSize = 2; protected AttributeAccess(String name) { - this.name = name.intern(); + this.name = Utils.intern(name); } public static AttributeAccess create(String name) { @@ -83,7 +84,7 @@ public abstract class AttributeAccess extends RBaseNode { return null; } - @Specialization(contains = {"accessCached", "accessCachedSize"}, rewriteOn = IndexOutOfBoundsException.class) + @Specialization(contains = {"accessCached", "accessCachedSize"}, guards = "attr.size() <= MAX_SIZE_BOUND") @ExplodeLoop protected Object accessCachedMaximumSize(RAttributes attr, // @Cached("create()") BranchProfile foundProfile, // @@ -91,9 +92,6 @@ public abstract class AttributeAccess extends RBaseNode { int size = attr.size(); if (size > maximumSize) { CompilerDirectives.transferToInterpreterAndInvalidate(); - if (size > MAX_SIZE_BOUND) { - throw new IndexOutOfBoundsException(); - } maximumSize = size; } for (int i = 0; i < maximumSize; i++) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java index 4f1a2ccad84568f50712f5df925f673209602a78..5bb402d333800d9d0f7e5a5b2450ee011a57840a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java @@ -107,25 +107,26 @@ public abstract class CopyAttributesNode extends RBaseNode { @Specialization(guards = {"leftLength == rightLength", "containsMetadata(left, attrLeftProfiles) || containsMetadata(right, attrRightProfiles)"}) protected RAbstractVector copySameLength(RAbstractVector target, RAbstractVector left, @SuppressWarnings("unused") int leftLength, RAbstractVector right, - @SuppressWarnings("unused") int rightLength, // - @Cached("create()") CopyOfRegAttributesNode copyOfRegLeft, // - @Cached("create()") CopyOfRegAttributesNode copyOfRegRight, // - @Cached("createDim()") RemoveAttributeNode removeDim, // - @Cached("createDimNames()") RemoveAttributeNode removeDimNames, // - @Cached("create()") InitAttributesNode initAttributes, // - @Cached("createNames()") PutAttributeNode putNames, // - @Cached("createDim()") PutAttributeNode putDim, // - @Cached("create()") BranchProfile leftHasDimensions, // - @Cached("create()") BranchProfile rightHasDimensions, // - @Cached("create()") BranchProfile noDimensions, // - @Cached("createBinaryProfile()") ConditionProfile hasNamesLeft, // - @Cached("createBinaryProfile()") ConditionProfile hasNamesRight, // + @SuppressWarnings("unused") int rightLength, + @Cached("create()") CopyOfRegAttributesNode copyOfRegLeft, + @Cached("create()") CopyOfRegAttributesNode copyOfRegRight, + @Cached("createBinaryProfile()") ConditionProfile hasAttributes, + @Cached("createDim()") RemoveAttributeNode removeDim, + @Cached("createDimNames()") RemoveAttributeNode removeDimNames, + @Cached("create()") InitAttributesNode initAttributes, + @Cached("createNames()") PutAttributeNode putNames, + @Cached("createDim()") PutAttributeNode putDim, + @Cached("create()") BranchProfile leftHasDimensions, + @Cached("create()") BranchProfile rightHasDimensions, + @Cached("create()") BranchProfile noDimensions, + @Cached("createBinaryProfile()") ConditionProfile hasNamesLeft, + @Cached("createBinaryProfile()") ConditionProfile hasNamesRight, @Cached("createBinaryProfile()") ConditionProfile hasDimNames) { if (LOG) { log("copyAttributes: =="); countEquals++; } - RVector result = target.materialize(); + RVector<?> result = target.materialize(); if (copyAllAttributes) { if (result != right) { copyOfRegRight.execute(right, result); @@ -141,23 +142,23 @@ public abstract class CopyAttributesNode extends RBaseNode { if (newDimensions == null) { noDimensions.enter(); RAttributes attributes = result.getAttributes(); - if (attributes != null) { + if (hasAttributes.profile(attributes != null)) { removeDim.execute(attributes); removeDimNames.execute(attributes); result.setInternalDimNames(null); } result.setInternalDimensions(null); - if (result != left) { - RStringVector vecNames = left.getNames(attrLeftProfiles); - if (hasNamesLeft.profile(vecNames != null)) { + RStringVector vecNames = left.getNames(attrLeftProfiles); + if (hasNamesLeft.profile(vecNames != null)) { + if (result != left) { putNames.execute(initAttributes.execute(result), vecNames); result.setInternalNames(vecNames); - return result; } + return result; } if (result != right) { - RStringVector vecNames = right.getNames(attrRightProfiles); + vecNames = right.getNames(attrRightProfiles); if (hasNamesRight.profile(vecNames != null)) { putNames.execute(initAttributes.execute(result), vecNames); result.setInternalNames(vecNames); @@ -209,7 +210,7 @@ public abstract class CopyAttributesNode extends RBaseNode { countSmaller++; } boolean rightNotResult = rightNotResultProfile.profile(right != target); - RVector result = target.materialize(); + RVector<?> result = target.materialize(); if (copyAllAttributes && rightNotResult) { copyOfReg.execute(right, result); } @@ -263,7 +264,7 @@ public abstract class CopyAttributesNode extends RBaseNode { log("copyAttributes: >"); countLarger++; } - RVector result = target.materialize(); + RVector<?> result = target.materialize(); if (copyAllAttributes && result != left) { copyOfReg.execute(left, result); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyOfRegAttributesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyOfRegAttributesNode.java index b066be22af2ab3675b97b82ef6d48ff6029d2223..b8ea14716d31665ae98772bf93e62ff79e7285e0 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyOfRegAttributesNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyOfRegAttributesNode.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.nodes.attributes; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RAttributes; import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; @@ -37,7 +38,9 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; */ public abstract class CopyOfRegAttributesNode extends RBaseNode { - public abstract void execute(RAbstractVector source, RVector target); + private final ConditionProfile sizeOneProfile = ConditionProfile.createBinaryProfile(); + + public abstract void execute(RAbstractVector source, RVector<?> target); public static CopyOfRegAttributesNode create() { return CopyOfRegAttributesNodeGen.create(); @@ -45,7 +48,7 @@ public abstract class CopyOfRegAttributesNode extends RBaseNode { @SuppressWarnings("unused") @Specialization(guards = "source.getAttributes() == null") - protected void copyNoAttributes(RAbstractVector source, RVector target) { + protected void copyNoAttributes(RAbstractVector source, RVector<?> target) { // nothing to do } @@ -56,44 +59,44 @@ public abstract class CopyOfRegAttributesNode extends RBaseNode { @SuppressWarnings("unused") @Specialization(guards = "emptyAttributes(source)", contains = "copyNoAttributes") - protected void copyEmptyAttributes(RAbstractVector source, RVector target) { + protected void copyEmptyAttributes(RAbstractVector source, RVector<?> target) { // nothing to do } - protected static final boolean onlyDimAttribute(RAbstractVector source) { + protected final boolean onlyDimAttribute(RAbstractVector source) { RAttributes attributes = source.getAttributes(); - return attributes != null && attributes.size() == 1 && attributes.getNameAtIndex(0) == RRuntime.DIM_ATTR_KEY; + return attributes != null && sizeOneProfile.profile(attributes.size() == 1) && attributes.getNameAtIndex(0) == RRuntime.DIM_ATTR_KEY; } @SuppressWarnings("unused") @Specialization(guards = "onlyDimAttribute(source)") - protected void copyDimOnly(RAbstractVector source, RVector target) { + protected void copyDimOnly(RAbstractVector source, RVector<?> target) { // nothing to do } - protected static final boolean onlyNamesAttribute(RAbstractVector source) { + protected final boolean onlyNamesAttribute(RAbstractVector source) { RAttributes attributes = source.getAttributes(); - return attributes != null && attributes.size() == 1 && attributes.getNameAtIndex(0) == RRuntime.NAMES_ATTR_KEY; + return attributes != null && sizeOneProfile.profile(attributes.size() == 1) && attributes.getNameAtIndex(0) == RRuntime.NAMES_ATTR_KEY; } @SuppressWarnings("unused") @Specialization(guards = "onlyNamesAttribute(source)") - protected void copyNamesOnly(RAbstractVector source, RVector target) { + protected void copyNamesOnly(RAbstractVector source, RVector<?> target) { // nothing to do } - protected static final boolean onlyClassAttribute(RAbstractVector source) { + protected final boolean onlyClassAttribute(RAbstractVector source) { RAttributes attributes = source.getAttributes(); - return attributes != null && attributes.size() == 1 && attributes.getNameAtIndex(0) == RRuntime.CLASS_ATTR_KEY; + return attributes != null && sizeOneProfile.profile(attributes.size() == 1) && attributes.getNameAtIndex(0) == RRuntime.CLASS_ATTR_KEY; } @Specialization(guards = "onlyClassAttribute(source)") - protected void copyClassOnly(RAbstractVector source, RVector target) { + protected void copyClassOnly(RAbstractVector source, RVector<?> target) { target.initAttributes(RAttributes.createInitialized(new String[]{RRuntime.CLASS_ATTR_KEY}, new Object[]{source.getAttributes().getValueAtIndex(0)})); } @Specialization - protected void copyGeneric(RAbstractVector source, RVector target) { + protected void copyGeneric(RAbstractVector source, RVector<?> target) { RAttributes orgAttributes = source.getAttributes(); if (orgAttributes != null) { Object newRowNames = null; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/PutAttributeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/PutAttributeNode.java index 2d23acf57927a512e833f6c78ae86a06588a0af7..63aa8f1df2624ae3172a7a798a84da2813f1a86b 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/PutAttributeNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/PutAttributeNode.java @@ -28,6 +28,7 @@ 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.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.data.RAttributes; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @@ -40,7 +41,7 @@ public abstract class PutAttributeNode extends RBaseNode { protected final String name; protected PutAttributeNode(String name) { - this.name = name.intern(); + this.name = Utils.intern(name); } public static PutAttributeNode create(String name) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/RemoveAttributeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/RemoveAttributeNode.java index e18922a2456c075ffdf671d5f18823b90388dad8..383346c0a9c895af629d39f95c8194422ba8eb3a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/RemoveAttributeNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/RemoveAttributeNode.java @@ -27,6 +27,7 @@ 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.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.data.RAttributes; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @@ -39,7 +40,7 @@ public abstract class RemoveAttributeNode extends RBaseNode { protected final String name; protected RemoveAttributeNode(String name) { - this.name = name.intern(); + this.name = Utils.intern(name); } public static RemoveAttributeNode create(String name) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/UnaryCopyAttributesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/UnaryCopyAttributesNode.java index 0d12ad9c1a8cdcce3a5ce8359ca12422e33fed45..e6f9d802e696bc4f99360bc4ff7761d45f200c55 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/UnaryCopyAttributesNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/UnaryCopyAttributesNode.java @@ -79,7 +79,7 @@ public abstract class UnaryCopyAttributesNode extends RBaseNode { @Cached("createBinaryProfile()") ConditionProfile noDimensions, // @Cached("createBinaryProfile()") ConditionProfile hasNamesSource, // @Cached("createBinaryProfile()") ConditionProfile hasDimNames) { - RVector result = target.materialize(); + RVector<?> result = target.materialize(); if (copyAllAttributes) { copyOfReg.execute(source, result); 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 615037cea562961a9c176a2d1cf2d851246cd71b..2a0cdac93ccdead042e5d958b99db3abf241aee1 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 @@ -69,7 +69,8 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.boxPrimitive(0).boxPrimitive(1); + casts.arg(0).boxPrimitive(); + casts.arg(1).boxPrimitive(); } public static BinaryArithmeticNode create(BinaryArithmeticFactory binary, UnaryArithmeticFactory unary) { 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 new file mode 100644 index 0000000000000000000000000000000000000000..0ab6d99fb1059867921d8b14e7d3fe94b8f6570b --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java @@ -0,0 +1,131 @@ +/* + * 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.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; +import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; +import com.oracle.truffle.r.runtime.ops.BinaryArithmeticFactory; + +/** + * Fast-path for scalar values: these cannot have any class attribute. Note: we intentionally use + * empty type system to avoid conversions to vector types. Some binary operations have simple NA + * handling, which is replicated here, others (notably pow and mul) throw + * {@link RSpecialFactory#FULL_CALL_NEEDED} on NA. + */ +@TypeSystemReference(EmptyTypeSystemFlatLayout.class) +@NodeChild(value = "arguments", 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 static RSpecialFactory createSpecialFactory(final BinaryArithmeticFactory opFactory) { + final boolean handleNA = !(opFactory == BinaryArithmetic.POW || opFactory == BinaryArithmetic.MOD); + boolean handleIntegers = !(opFactory == BinaryArithmetic.POW || opFactory == BinaryArithmetic.DIV); + if (handleIntegers) { + return (signature, arguments) -> signature.getNonNullCount() == 0 && arguments.length == 2 + ? IntegerBinaryArithmeticSpecialNodeGen.create(opFactory.create(), handleNA, arguments) : null; + } else { + return (signature, arguments) -> signature.getNonNullCount() == 0 && arguments.length == 2 ? BinaryArithmeticSpecialNodeGen.create(opFactory.create(), handleNA, arguments) + : null; + } + } + + @Specialization + protected double doDoubles(double left, double right) { + if (RRuntime.isNA(left) || RRuntime.isNA(right)) { + checkFullCallNeededOnNA(); + return RRuntime.DOUBLE_NA; + } + return getOperation().op(left, right); + } + + @Fallback + @SuppressWarnings("unused") + protected void doFallback(Object left, Object right) { + throw RSpecialFactory.FULL_CALL_NEEDED; + } + + protected BinaryArithmetic getOperation() { + return operation; + } + + protected void checkFullCallNeededOnNA() { + if (!handleNA) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + throw RSpecialFactory.FULL_CALL_NEEDED; + } + } + + /** + * Adds integers handling. + */ + abstract static class IntegerBinaryArithmeticSpecial extends BinaryArithmeticSpecial { + + IntegerBinaryArithmeticSpecial(BinaryArithmetic op, boolean handleNA) { + super(op, handleNA); + } + + @Specialization + public int doIntegers(int left, int right, @Cached("createBinaryProfile()") ConditionProfile naProfile) { + if (naProfile.profile(RRuntime.isNA(left) || RRuntime.isNA(right))) { + checkFullCallNeededOnNA(); + return RRuntime.INT_NA; + } + return getOperation().op(left, right); + } + + @Specialization + public double doIntDouble(int left, double right, @Cached("createBinaryProfile()") ConditionProfile naProfile) { + if (naProfile.profile(RRuntime.isNA(left) || RRuntime.isNA(right))) { + checkFullCallNeededOnNA(); + return RRuntime.DOUBLE_NA; + } + return getOperation().op(left, right); + } + + @Specialization + public double doDoubleInt(double left, int right, @Cached("createBinaryProfile()") ConditionProfile naProfile) { + if (naProfile.profile(RRuntime.isNA(left) || RRuntime.isNA(right))) { + checkFullCallNeededOnNA(); + return RRuntime.DOUBLE_NA; + } + return getOperation().op(left, right); + } + } +} 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 35a3e16ad6cc4b751b3fbbe51fd779a81ee919b9..baf03bf896a421ab3777708a6337204cd560bcb2 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 @@ -69,7 +69,8 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.boxPrimitive(0).boxPrimitive(1); + casts.arg(0).boxPrimitive(); + casts.arg(1).boxPrimitive(); } private static boolean isLogicOp(BooleanOperation op) { 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 new file mode 100644 index 0000000000000000000000000000000000000000..c931c5f43549eca7f4dc3e4529cf65e6c3ebf3aa --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanSpecial.java @@ -0,0 +1,97 @@ +/* + * 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.binary; + +import com.oracle.truffle.api.CompilerDirectives; +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; +import com.oracle.truffle.r.runtime.ops.BooleanOperation; +import com.oracle.truffle.r.runtime.ops.BooleanOperationFactory; + +/** + * Fast-path for scalar values: these cannot have any class attribute. Note: we intentionally use + * empty type system to avoid conversions to vector types. NA values cause + * {@link RSpecialFactory#FULL_CALL_NEEDED} exception. + */ +@TypeSystemReference(EmptyTypeSystemFlatLayout.class) +@NodeChild(value = "arguments", type = RNode[].class) +public abstract class BinaryBooleanSpecial extends RNode { + @Child private BooleanOperation operation; + + protected BinaryBooleanSpecial(BooleanOperation operation) { + this.operation = operation; + } + + public static RSpecialFactory createSpecialFactory(final BooleanOperationFactory opFactory) { + return (signature, arguments) -> signature.getNonNullCount() == 0 && arguments.length == 2 ? BinaryBooleanSpecialNodeGen.create(opFactory.create(), arguments) : null; + } + + @Specialization + public byte doInts(int left, int right) { + if (RRuntime.isNA(left) || RRuntime.isNA(right)) { + return handleNA(); + } + return RRuntime.asLogical(operation.op(left, right)); + } + + @Specialization + public byte doDoubles(double left, double right) { + if (!RRuntime.isFinite(left) || !RRuntime.isFinite(right)) { + return handleNA(); + } + return RRuntime.asLogical(operation.op(left, right)); + } + + @Specialization + public byte doIntDouble(int left, double right) { + if (RRuntime.isNA(left) || !RRuntime.isFinite(right)) { + return handleNA(); + } + return RRuntime.asLogical(operation.op(left, right)); + } + + @Specialization + public byte doDoubleInt(double left, int right) { + if (!RRuntime.isFinite(left) || RRuntime.isNA(right)) { + return handleNA(); + } + return RRuntime.asLogical(operation.op(left, right)); + } + + @Fallback + @SuppressWarnings("unused") + public void doFallback(Object left, Object right) { + throw RSpecialFactory.FULL_CALL_NEEDED; + } + + private byte handleNA() { + CompilerDirectives.transferToInterpreterAndInvalidate(); + throw RSpecialFactory.FULL_CALL_NEEDED; + } +} 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 066584b4464660494141eb18942407f8ef2df75f..d119d793514f57cfa0cc9899a6e3442ec2ac389a 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 @@ -81,6 +81,7 @@ public final class BinaryMapArithmeticFunctionNode extends BinaryMapNAFunctionNo @Override public double applyDouble(double left, double right) { if (leftNACheck.check(left)) { + // Note: these corner cases also apply in BinaryArithmeticSpecial node if (this.arithmetic instanceof BinaryArithmetic.Pow && right == 0) { // CORNER: Make sure NA^0 == 1 return 1; 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 6d813c4a45aa5e8d837aa4b520e374ca167f0980..245067ec8469059f34357adc436ef56abbfef8a0 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 @@ -70,7 +70,7 @@ public abstract class CastTypeNode extends BinaryNode { public static CastNode createCast(RType type, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { switch (type) { case Character: - return CastStringNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, false); + return CastStringNodeGen.create(preserveNames, preserveDimensions, preserveAttributes); case Complex: return CastComplexNodeGen.create(preserveNames, preserveDimensions, preserveAttributes); case Double: diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/AbstractPredicateArgumentFilter.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/AbstractPredicateArgumentFilter.java index 43f0fe3d1355ae55e1647c1c8dc6537b8e7ea5ea..2dcc0afe90feec17d81b01fef0ab60b791cbd3b1 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/AbstractPredicateArgumentFilter.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/AbstractPredicateArgumentFilter.java @@ -24,29 +24,18 @@ package com.oracle.truffle.r.nodes.builtin; import java.util.function.Predicate; -import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.ArgumentFilter.NarrowingArgumentFilter; -import com.oracle.truffle.r.runtime.data.RNull; public abstract class AbstractPredicateArgumentFilter<T, R extends T> implements NarrowingArgumentFilter<T, R> { private final Predicate<? super T> valuePredicate; - private final boolean isNullable; - private final ConditionProfile profile = ConditionProfile.createBinaryProfile(); - - public AbstractPredicateArgumentFilter(Predicate<? super T> valuePredicate, boolean isNullable) { + public AbstractPredicateArgumentFilter(Predicate<? super T> valuePredicate) { this.valuePredicate = valuePredicate; - this.isNullable = isNullable; } @Override public boolean test(T arg) { - if (profile.profile(!isNullable && (arg == RNull.instance || arg == null))) { - return false; - } else { - return valuePredicate.test(arg == RNull.instance ? null : arg); - } + return valuePredicate.test(arg); } - } 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 7ced392e8699d325fe7d394241114e406f251064..c7f6bc6ef0902217fbd27c9c934c964dba756359 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,1702 +23,730 @@ package com.oracle.truffle.r.nodes.builtin; import java.util.Arrays; -import java.util.Objects; -import java.util.function.Function; - -import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen; -import com.oracle.truffle.r.nodes.builtin.ArgumentFilter.ArgumentTypeFilter; -import com.oracle.truffle.r.nodes.builtin.ArgumentFilter.ArgumentValueFilter; -import com.oracle.truffle.r.nodes.unary.CastDoubleBaseNodeGen; -import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen; -import com.oracle.truffle.r.nodes.unary.CastIntegerBaseNodeGen; -import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; -import com.oracle.truffle.r.nodes.unary.CastLogicalBaseNodeGen; -import com.oracle.truffle.r.nodes.unary.CastLogicalNodeGen; +import java.util.function.Consumer; + +import com.oracle.truffle.api.CompilerDirectives; +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.MatrixFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.NotFilter; +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.MessageData; +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.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.PipelineToCastNode; +import com.oracle.truffle.r.nodes.builtin.casts.fluent.ChainBuilder; +import com.oracle.truffle.r.nodes.builtin.casts.fluent.FindFirstNodeBuilder; +import com.oracle.truffle.r.nodes.builtin.casts.fluent.InitialPhaseBuilder; +import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineBuilder; +import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineConfigBuilder; +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.CastStringBaseNodeGen; -import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; -import com.oracle.truffle.r.nodes.unary.CastToAttributableNodeGen; -import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen; -import com.oracle.truffle.r.nodes.unary.ChainedCastNode; -import com.oracle.truffle.r.nodes.unary.ConditionalMapNodeGen; -import com.oracle.truffle.r.nodes.unary.FilterNodeGen; -import com.oracle.truffle.r.nodes.unary.FindFirstNodeGen; -import com.oracle.truffle.r.nodes.unary.FirstBooleanNodeGen; -import com.oracle.truffle.r.nodes.unary.FirstIntNode; -import com.oracle.truffle.r.nodes.unary.FirstStringNode; -import com.oracle.truffle.r.nodes.unary.MapNodeGen; -import com.oracle.truffle.r.nodes.unary.NonNANodeGen; 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.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.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.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; import com.oracle.truffle.r.runtime.nodes.RBaseNode; public final class CastBuilder { - private static final CastNode[] EMPTY_CASTS_ARRAY = new CastNode[0]; + private static final PipelineBuilder[] EMPTY_BUILDERS = new PipelineBuilder[0]; - private final RBuiltinNode builtinNode; + private final RBuiltin builtin; + private final String[] argumentNames; + private PipelineBuilder[] argumentBuilders; + private CastNode[] castsCache = null; - private CastNode[] casts = EMPTY_CASTS_ARRAY; - - public CastBuilder(RBuiltinNode builtinNode) { - this.builtinNode = builtinNode; - } - - public CastBuilder() { - this(null); - } - - private CastBuilder insert(int index, CastNode cast) { - if (index >= casts.length) { - casts = Arrays.copyOf(casts, index + 1); - } - if (casts[index] == null) { - casts[index] = cast; + public CastBuilder(RBuiltin builtin) { + // Note: if we have the builtin metadata, we pre-allocate the arrays, builtinNode != null is + // used to determine, if the arrays are pre-allocated or if they can grow + if (builtin == null) { + this.builtin = null; + argumentNames = null; + argumentBuilders = EMPTY_BUILDERS; } else { - casts[index] = new ChainedCastNode(casts[index], cast); + this.builtin = builtin; + argumentNames = builtin.parameterNames(); + argumentBuilders = new PipelineBuilder[builtin.parameterNames().length]; } - return this; - } - - public CastNode[] getCasts() { - return casts; - } - - public CastBuilder toAttributable(int index, boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { - return insert(index, CastToAttributableNodeGen.create(preserveNames, dimensionsPreservation, attrPreservation)); - } - - public CastBuilder toVector(int index) { - return insert(index, CastToVectorNodeGen.create(false)); - } - - public CastBuilder toInteger(int index) { - return toInteger(index, false, false, false); - } - - public CastBuilder toInteger(int index, boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { - return insert(index, CastIntegerNodeGen.create(preserveNames, dimensionsPreservation, attrPreservation)); - } - - public CastBuilder toDouble(int index) { - return toDouble(index, false, false, false); - } - - public CastBuilder toDouble(int index, boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { - return insert(index, CastDoubleNodeGen.create(preserveNames, dimensionsPreservation, attrPreservation)); - } - - public CastBuilder toLogical(int index) { - return insert(index, CastLogicalNodeGen.create(false, false, false)); - } - - public CastBuilder toCharacter(int index) { - return insert(index, CastStringNodeGen.create(false, false, false, false)); - } - - public CastBuilder boxPrimitive(int index) { - return insert(index, BoxPrimitiveNodeGen.create()); - } - - public CastBuilder custom(int index, CastNode cast) { - return insert(index, cast); - } - - public CastBuilder firstIntegerWithWarning(int index, int intNa, String name) { - insert(index, CastIntegerNodeGen.create(false, false, false)); - return insert(index, FirstIntNode.createWithWarning(RError.Message.FIRST_ELEMENT_USED, name, intNa)); - } - - public CastBuilder firstIntegerWithError(int index, RError.Message error, String name) { - insert(index, CastIntegerNodeGen.create(false, false, false)); - return insert(index, FirstIntNode.createWithError(error, name)); - } - - public CastBuilder firstStringWithError(int index, RError.Message error, String name) { - return insert(index, FirstStringNode.createWithError(error, name)); - } - - public CastBuilder firstBoolean(int index) { - return insert(index, FirstBooleanNodeGen.create(null)); - } - - public CastBuilder firstBoolean(int index, String invalidValueName) { - return insert(index, FirstBooleanNodeGen.create(invalidValueName)); - } - - public CastBuilder firstLogical(int index) { - arg(index).asLogicalVector().findFirst(RRuntime.LOGICAL_NA); - return this; } - public InitialPhaseBuilder<Object> arg(int argumentIndex, String argumentName) { - return new ArgCastBuilderFactoryImpl(argumentIndex, argumentName).newInitialPhaseBuilder(); + public CastBuilder(int argumentsCount) { + assert argumentsCount >= 0 : "argumentsCount must be non-negative"; + builtin = null; + argumentNames = null; + argumentBuilders = new PipelineBuilder[argumentsCount]; } - public InitialPhaseBuilder<Object> arg(int argumentIndex) { - return arg(argumentIndex, builtinNode == null ? null : builtinNode.getRBuiltin().parameterNames()[argumentIndex]); + public CastBuilder() { + builtin = null; + argumentNames = null; + argumentBuilders = EMPTY_BUILDERS; } - public InitialPhaseBuilder<Object> arg(String argumentName) { - return arg(getArgumentIndex(argumentName), argumentName); + /** + * Returns the first case node in the chain for each argument, if argument does not require any + * casting, returns {@code null} as its cast node. + */ + public CastNode[] getCasts() { + if (castsCache == null) { + castsCache = new CastNode[argumentBuilders.length]; + for (int i = 0; i < argumentBuilders.length; i++) { + PipelineBuilder arg = argumentBuilders[i]; + if (arg != null) { + castsCache[i] = PipelineToCastNode.convert(arg.getPipelineConfig().build(), arg.getFirstStep()); + } + } + } + return castsCache; + } + + // --------------------- + // The cast-pipelines API starts here + + /** + * Returns a builder of a cast pipeline for the given argument name. + * <p> + * The process of building a cast pipeline proceeds in up-to four phases: + * + * <pre> + * Pre-initialPhase -> (InitialPhase -> (CoercedPhase -> HeadPhase?)?)? + * </pre> + * + * 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 + * {@link PreinitialPhaseBuilder} class, e.g. {@link PreinitialPhaseBuilder#allowNull()}. + * </p> + * <p> + * In the initial phase, the pipeline can be configured to filter or to coerce the input + * argument to one of the available vector types. By using filters one can narrow down the + * expected type of the argument. The API reflects that narrowing type in subsequent builder + * steps. Other filters can put constrains on argument values. Filter conditions can be combined + * by means of <code>and</code>, <code>or</code> and <code>not</code> operators. To coerce the + * input argument to a vector one of the <code>as<X>Vector</code> steps is used, where + * <code>X</code> is the element type of the given vector. Using a coercion step leads to the + * transition to the coerced phase. + * </p> + * <p> + * In the coerced phase one can specify filters examining a vector argument's properties, such + * as the size or dimensions. The coerced phase can be followed by the head phase once a + * {@code findFirst} step is used. In this phase the vector argument type is narrowed down to a + * scalar value. + * </p> + * <p> + * During any phase, one can add filter and mapper steps. The methods creating such steps, e.g. + * {@link InitialPhaseBuilder#mustBe(Filter)}, usually take {@link Filter} or {@link Mapper} + * instance. Use convenient static methods in the {@link Predef} class to construct these + * instances. + * </p> + * <p> + * Notable is the {@code mapIf} step, which allows to split the pipeline into two eventualities + * depending on the filter condition. The second and third argument, namely + * {@code trueBranchMapper} and {@code falseBranchMapper}, can be simple mappers, e.g. + * {@link Predef#toBoolean()} or one can construct more complex mapping using + * {@link Predef#chain(PipelineStep)} invocation followed by {@code with(step)} calls and + * finished by {@code end()} invocation. The steps can be constructed using convenient methods + * in the {@link Predef} class. + * + * Note: For technical reasons, when using 'find first' step by means of + * {@link Predef#findFirst()} in this situation, it must be followed by call to + * {@link FindFirstNodeBuilder#integerElement()} or other similar method corresponding to the + * expected element type. + * </p> + * + * <h2>Handling {@code RNull} and {@code RMissing} values</h2> By default, {@code RNull} and + * {@code 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 {@code FindFirstNode} node replaces + * both {@code RNull} and {@code RMissing} by the replacement values specified in the + * corresponding <code>findFirst(repl)</code> pipeline step. Also the {@code CastToVectorNode} + * coercion node replaces those values by an empty list provided that the + * <code>isPreserveNonVector</code> flag is set. + * + * <h3>Overriding the default behavior</h3> A cast pipeline can be configured not to send + * {@code RNull} and/or {@code 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: + * + * <pre> + * 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. + * </pre> + * + * Analogous methods exist for {@code RMissing}. + */ + public PreinitialPhaseBuilder<Object> arg(String argumentName) { + assert builtin != null : "arg(String) is only supported for builtins cast pipelines"; + return new PreinitialPhaseBuilder<>(getBuilder(getArgumentIndex(argumentName), argumentName)); + } + + /** + * @see #arg(String) + */ + public PreinitialPhaseBuilder<Object> arg(int argumentIndex, String argumentName) { + assert builtin != null : "arg(int, String) is only supported for builtins cast pipelines"; + assert argumentIndex >= 0 && argumentIndex < argumentBuilders.length : "argument index out of range"; + assert argumentNames[argumentIndex].equals(argumentName) : "wrong argument name " + argumentName; + return new PreinitialPhaseBuilder<>(getBuilder(argumentIndex, argumentName)); + } + + /** + * @see #arg(String) + */ + public PreinitialPhaseBuilder<Object> arg(int argumentIndex) { + boolean existingIndex = argumentNames != null && argumentIndex >= 0 && argumentIndex < argumentNames.length; + String name = existingIndex ? argumentNames[argumentIndex] : null; + return new PreinitialPhaseBuilder<>(getBuilder(argumentIndex, name)); + } + + private PipelineBuilder getBuilder(int argumentIndex, String argumentName) { + if (builtin == null && argumentIndex >= argumentBuilders.length) { + // in the case that we have a builtin, the arguments size is known and fixed, otherwise + // we grow the array accordingly + argumentBuilders = Arrays.copyOf(argumentBuilders, argumentIndex + 1); + } + if (argumentBuilders[argumentIndex] == null) { + argumentBuilders[argumentIndex] = new PipelineBuilder(new PipelineConfigBuilder(argumentName)); + } + return argumentBuilders[argumentIndex]; } private int getArgumentIndex(String argumentName) { - if (builtinNode == null) { + if (builtin == null) { throw new IllegalArgumentException("No builtin node associated with cast builder"); } - String[] parameterNames = builtinNode.getRBuiltin().parameterNames(); - for (int i = 0; i < parameterNames.length; i++) { - if (argumentName.equals(parameterNames[i])) { + for (int i = 0; i < argumentNames.length; i++) { + if (argumentName.equals(argumentNames[i])) { return i; } } - throw RInternalError.shouldNotReachHere(String.format("Argument %s not found in builtin %s", argumentName, builtinNode.getRBuiltin().name())); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - public static Object[] substituteArgPlaceholder(Object arg, Object[] messageArgs) { - Object[] newMsgArgs = Arrays.copyOf(messageArgs, messageArgs.length); - - for (int i = 0; i < messageArgs.length; i++) { - final Object msgArg = messageArgs[i]; - if (msgArg instanceof Function) { - newMsgArgs[i] = ((Function) msgArg).apply(arg); - } - } - - return newMsgArgs; - } - - public interface PredefFilters { - - <T> ValuePredicateArgumentFilter<T> sameAs(T x); - - <T> ValuePredicateArgumentFilter<T> equalTo(T x); - - <T, R extends T> TypePredicateArgumentFilter<T, R> nullValue(); - - <T extends RAbstractVector> VectorPredicateArgumentFilter<T> notEmpty(); - - <T extends RAbstractVector> VectorPredicateArgumentFilter<T> singleElement(); - - <T extends RAbstractVector, R extends T> VectorPredicateArgumentFilter<T> size(int s); - - VectorPredicateArgumentFilter<RAbstractStringVector> elementAt(int index, String value); - - VectorPredicateArgumentFilter<RAbstractIntVector> elementAt(int index, int value); - - VectorPredicateArgumentFilter<RAbstractDoubleVector> elementAt(int index, double value); - - VectorPredicateArgumentFilter<RAbstractComplexVector> elementAt(int index, RComplex value); - - VectorPredicateArgumentFilter<RAbstractLogicalVector> elementAt(int index, byte value); - - ValuePredicateArgumentFilter<Boolean> trueValue(); - - ValuePredicateArgumentFilter<Boolean> falseValue(); - - ValuePredicateArgumentFilter<Byte> logicalTrue(); - - ValuePredicateArgumentFilter<Byte> logicalFalse(); - - ValuePredicateArgumentFilter<Integer> intNA(); - - ValuePredicateArgumentFilter<Byte> logicalNA(); - - ValuePredicateArgumentFilter<Double> doubleNA(); - - ValuePredicateArgumentFilter<String> stringNA(); - - ValuePredicateArgumentFilter<Integer> eq(int x); - - ValuePredicateArgumentFilter<Double> eq(double x); - - ValuePredicateArgumentFilter<Integer> gt(int x); - - ValuePredicateArgumentFilter<Double> gt(double x); - - ValuePredicateArgumentFilter<Double> gte(double x); - - ValuePredicateArgumentFilter<Integer> lt(int x); - - ValuePredicateArgumentFilter<Double> lt(double x); - - ValuePredicateArgumentFilter<Double> lte(double x); - - ValuePredicateArgumentFilter<String> length(int l); - - ValuePredicateArgumentFilter<String> lengthGt(int l); - - ValuePredicateArgumentFilter<String> lengthLt(int l); - - <R> TypePredicateArgumentFilter<Object, R> instanceOf(Class<R> cls); - - <R extends RAbstractIntVector> TypePredicateArgumentFilter<Object, R> integerValue(); - - <R extends RAbstractStringVector> TypePredicateArgumentFilter<Object, R> stringValue(); - - <R extends RAbstractDoubleVector> TypePredicateArgumentFilter<Object, R> doubleValue(); - - <R extends RAbstractLogicalVector> TypePredicateArgumentFilter<Object, R> logicalValue(); - - <R extends RAbstractComplexVector> TypePredicateArgumentFilter<Object, R> complexValue(); - - TypePredicateArgumentFilter<Object, String> scalarStringValue(); - - TypePredicateArgumentFilter<Object, Integer> scalarIntegerValue(); - - TypePredicateArgumentFilter<Object, Double> scalarDoubleValue(); - - TypePredicateArgumentFilter<Object, Byte> scalarLogicalValue(); - - TypePredicateArgumentFilter<Object, RComplex> scalarComplexValue(); - - TypePredicateArgumentFilter<Object, RMissing> missingValue(); - - } - - public interface PredefMappers { - ValuePredicateArgumentMapper<Byte, Boolean> toBoolean(); - - ValuePredicateArgumentMapper<String, Integer> charAt0(int defaultValue); - - <T> ValuePredicateArgumentMapper<T, RNull> nullConstant(); - - ValuePredicateArgumentMapper<String, String> constant(String s); - - ValuePredicateArgumentMapper<Integer, Integer> constant(int i); - - ValuePredicateArgumentMapper<Double, Double> constant(double d); - - ValuePredicateArgumentMapper<Byte, Byte> constant(byte l); - - <T> ArgumentMapper<T, T> defaultValue(T defVal); - + CompilerDirectives.transferToInterpreter(); + throw RInternalError.shouldNotReachHere(String.format("Argument %s not found in builtin %s", argumentName, builtin.name())); } - public static final class DefaultPredefFilters implements PredefFilters { - - @Override - public <T> ValuePredicateArgumentFilter<T> sameAs(T x) { - return ValuePredicateArgumentFilter.fromLambda(arg -> arg == x); - } - - @Override - public <T> ValuePredicateArgumentFilter<T> equalTo(T x) { - return ValuePredicateArgumentFilter.fromLambda(arg -> Objects.equals(arg, x)); - } - - @Override - public <T, R extends T> TypePredicateArgumentFilter<T, R> nullValue() { - return new TypePredicateArgumentFilter<>(x -> x == RNull.instance || x == null, true); - } - - @Override - public <T extends RAbstractVector> VectorPredicateArgumentFilter<T> notEmpty() { - return new VectorPredicateArgumentFilter<>(x -> x.getLength() > 0, false); - } - - @Override - public <T extends RAbstractVector> VectorPredicateArgumentFilter<T> singleElement() { - return new VectorPredicateArgumentFilter<>(x -> x.getLength() == 1, false); - } - - @Override - public <T extends RAbstractVector, R extends T> VectorPredicateArgumentFilter<T> size(int s) { - return new VectorPredicateArgumentFilter<>(x -> x.getLength() == s, false); - } - - @Override - public VectorPredicateArgumentFilter<RAbstractStringVector> elementAt(int index, String value) { - return new VectorPredicateArgumentFilter<>(x -> index < x.getLength() && value.equals(x.getDataAtAsObject(index)), false); - } - - @Override - public VectorPredicateArgumentFilter<RAbstractIntVector> elementAt(int index, int value) { - return new VectorPredicateArgumentFilter<>(x -> index < x.getLength() && value == (int) x.getDataAtAsObject(index), false); - } - - @Override - public VectorPredicateArgumentFilter<RAbstractDoubleVector> elementAt(int index, double value) { - return new VectorPredicateArgumentFilter<>(x -> index < x.getLength() && value == (double) x.getDataAtAsObject(index), false); - } - - @Override - public VectorPredicateArgumentFilter<RAbstractComplexVector> elementAt(int index, RComplex value) { - return new VectorPredicateArgumentFilter<>(x -> index < x.getLength() && value.equals(x.getDataAtAsObject(index)), false); - } - - @Override - public VectorPredicateArgumentFilter<RAbstractLogicalVector> elementAt(int index, byte value) { - return new VectorPredicateArgumentFilter<>(x -> index < x.getLength() && value == (byte) (x.getDataAtAsObject(index)), false); - } - - @Override - public ValuePredicateArgumentFilter<Boolean> trueValue() { - return ValuePredicateArgumentFilter.fromLambda(x -> x); - } - - @Override - public ValuePredicateArgumentFilter<Boolean> falseValue() { - return ValuePredicateArgumentFilter.fromLambda(x -> x); - } - - @Override - public ValuePredicateArgumentFilter<Byte> logicalTrue() { - return ValuePredicateArgumentFilter.fromLambda(x -> RRuntime.LOGICAL_TRUE == x); - } - - @Override - public ValuePredicateArgumentFilter<Byte> logicalFalse() { - return ValuePredicateArgumentFilter.fromLambda(x -> RRuntime.LOGICAL_FALSE == x); - } - - @Override - public ValuePredicateArgumentFilter<Integer> intNA() { - return ValuePredicateArgumentFilter.fromLambda((Integer x) -> RRuntime.isNA(x)); - } - - @Override - public ValuePredicateArgumentFilter<Byte> logicalNA() { - return ValuePredicateArgumentFilter.fromLambda((Byte x) -> RRuntime.isNA(x)); - } - - @Override - public ValuePredicateArgumentFilter<Double> doubleNA() { - return ValuePredicateArgumentFilter.fromLambda((Double x) -> RRuntime.isNA(x)); - } - - @Override - public ValuePredicateArgumentFilter<String> stringNA() { - return ValuePredicateArgumentFilter.fromLambda((String x) -> RRuntime.isNA(x)); - } - - @Override - public ValuePredicateArgumentFilter<Integer> eq(int x) { - return ValuePredicateArgumentFilter.fromLambda((Integer arg) -> arg != null && arg.intValue() == x); - } + public static final class Predef { - @Override - public ValuePredicateArgumentFilter<Double> eq(double x) { - return ValuePredicateArgumentFilter.fromLambda((Double arg) -> arg != null && arg.doubleValue() == x); + @SuppressWarnings("unchecked") + public static <T> NotFilter<T> not(Filter<? super T, ? extends T> filter) { + NotFilter<? super T> n = filter.not(); + return (NotFilter<T>) n; } - @Override - public ValuePredicateArgumentFilter<Integer> gt(int x) { - return ValuePredicateArgumentFilter.fromLambda((Integer arg) -> arg != null && arg > x); + public static <T> AndFilter<T, T> and(Filter<T, T> filter1, Filter<T, T> filter2) { + return filter1.and(filter2); } - @Override - public ValuePredicateArgumentFilter<Double> gt(double x) { - return ValuePredicateArgumentFilter.fromLambda((Double arg) -> arg != null && arg > x); + public static <T> OrFilter<T> or(Filter<T, T> filter1, Filter<T, T> filter2) { + return filter1.or(filter2); } - @Override - public ValuePredicateArgumentFilter<Double> gte(double x) { - return ValuePredicateArgumentFilter.fromLambda((Double arg) -> arg != null && arg >= x); + 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); } - @Override - public ValuePredicateArgumentFilter<Integer> lt(int x) { - return ValuePredicateArgumentFilter.fromLambda((Integer arg) -> arg != null && arg < x); + public static <T, R extends T> PipelineStep<T, R> mustBe(Filter<T, R> argFilter) { + return mustBe(argFilter, null, null); } - @Override - public ValuePredicateArgumentFilter<Double> lt(double x) { - return ValuePredicateArgumentFilter.fromLambda((Double arg) -> arg < x); + 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); } - @Override - public ValuePredicateArgumentFilter<Double> lte(double x) { - return ValuePredicateArgumentFilter.fromLambda((Double arg) -> arg <= x); + public static <T> PipelineStep<T, T> shouldBe(Filter<T, ? extends T> argFilter) { + return shouldBe(argFilter, null, null); } - @Override - public ValuePredicateArgumentFilter<String> length(int l) { - return ValuePredicateArgumentFilter.fromLambda((String arg) -> arg != null && arg.length() == l); + public static <T, R> PipelineStep<T, R> map(Mapper<T, R> mapper) { + return new MapStep<>(mapper); } - @Override - public ValuePredicateArgumentFilter<String> lengthGt(int l) { - return ValuePredicateArgumentFilter.fromLambda((String arg) -> arg != null && arg.length() > l); + public static <T, S extends T, R> PipelineStep<T, R> mapIf(Filter<? super T, S> filter, PipelineStep<?, ?> trueBranch, PipelineStep<?, ?> falseBranch) { + return new MapIfStep<>(filter, trueBranch, falseBranch); } - @Override - public ValuePredicateArgumentFilter<String> lengthLt(int l) { - return ValuePredicateArgumentFilter.fromLambda((String arg) -> arg != null && arg.length() < l); + public static <T, S extends T, R> PipelineStep<T, R> mapIf(Filter<? super T, S> filter, PipelineStep<?, ?> trueBranch) { + return mapIf(filter, trueBranch, null); } - @Override - public <R> TypePredicateArgumentFilter<Object, R> instanceOf(Class<R> cls) { - return TypePredicateArgumentFilter.fromLambda(x -> cls.isInstance(x)); + public static <T> ChainBuilder<T> chain(PipelineStep<T, ?> firstStep) { + return new ChainBuilder<>(firstStep); } - @Override - public <R extends RAbstractIntVector> TypePredicateArgumentFilter<Object, R> integerValue() { - return TypePredicateArgumentFilter.fromLambda(x -> x instanceof Integer || x instanceof RAbstractIntVector); + public static <T> PipelineStep<T, Integer> asInteger() { + return new CoercionStep<>(RType.Integer, false); } - @Override - public <R extends RAbstractStringVector> TypePredicateArgumentFilter<Object, R> stringValue() { - return TypePredicateArgumentFilter.fromLambda(x -> x instanceof String || x instanceof RAbstractStringVector); + public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVector() { + return new CoercionStep<>(RType.Integer, true); } - @Override - public <R extends RAbstractDoubleVector> TypePredicateArgumentFilter<Object, R> doubleValue() { - return TypePredicateArgumentFilter.fromLambda(x -> x instanceof Double || x instanceof RAbstractDoubleVector); + public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { + return new CoercionStep<>(RType.Integer, true, preserveNames, preserveDimensions, preserveAttributes); } - @Override - public <R extends RAbstractLogicalVector> TypePredicateArgumentFilter<Object, R> logicalValue() { - return TypePredicateArgumentFilter.fromLambda(x -> x instanceof Byte || x instanceof RAbstractLogicalVector); + public static <T> PipelineStep<T, Double> asDouble() { + return new CoercionStep<>(RType.Double, false); } - @Override - public <R extends RAbstractComplexVector> TypePredicateArgumentFilter<Object, R> complexValue() { - return TypePredicateArgumentFilter.fromLambda(x -> x instanceof RComplex || x instanceof RAbstractComplexVector); + public static <T> PipelineStep<T, RAbstractDoubleVector> asDoubleVector() { + return new CoercionStep<>(RType.Double, true); } - @Override - public TypePredicateArgumentFilter<Object, String> scalarStringValue() { - return TypePredicateArgumentFilter.fromLambda(x -> x instanceof String); + public static <T> PipelineStep<T, RAbstractDoubleVector> asDoubleVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { + return new CoercionStep<>(RType.Double, true, preserveNames, preserveDimensions, preserveAttributes); } - @Override - public TypePredicateArgumentFilter<Object, Integer> scalarIntegerValue() { - return TypePredicateArgumentFilter.fromLambda(x -> x instanceof Integer); + public static <T> PipelineStep<T, String> asString() { + return new CoercionStep<>(RType.Character, false); } - @Override - public TypePredicateArgumentFilter<Object, Double> scalarDoubleValue() { - return TypePredicateArgumentFilter.fromLambda(x -> x instanceof Double); + public static <T> PipelineStep<T, RAbstractStringVector> asStringVector() { + return new CoercionStep<>(RType.Character, true); } - @Override - public TypePredicateArgumentFilter<Object, Byte> scalarLogicalValue() { - return TypePredicateArgumentFilter.fromLambda(x -> x instanceof Byte); + public static <T> PipelineStep<T, RAbstractStringVector> asStringVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { + return new CoercionStep<>(RType.Character, true, preserveNames, preserveDimensions, preserveAttributes); } - @Override - public TypePredicateArgumentFilter<Object, RComplex> scalarComplexValue() { - return TypePredicateArgumentFilter.fromLambda(x -> x instanceof RComplex); + public static <T> PipelineStep<T, RAbstractComplexVector> asComplexVector() { + return new CoercionStep<>(RType.Complex, true); } - @Override - public TypePredicateArgumentFilter<Object, RMissing> missingValue() { - return TypePredicateArgumentFilter.fromLambda(x -> RMissing.instance == x); + public static <T> PipelineStep<T, RAbstractRawVector> asRawVector() { + return new CoercionStep<>(RType.Raw, true); } - } - - public static final class DefaultPredefMappers implements PredefMappers { - - @Override - public ValuePredicateArgumentMapper<Byte, Boolean> toBoolean() { - return ValuePredicateArgumentMapper.fromLambda(x -> RRuntime.fromLogical(x)); - } - - @Override - public ValuePredicateArgumentMapper<String, Integer> charAt0(int defaultValue) { - final ConditionProfile profile = ConditionProfile.createBinaryProfile(); - final ConditionProfile profile2 = ConditionProfile.createBinaryProfile(); - return ValuePredicateArgumentMapper.fromLambda(x -> { - if (profile.profile(x == null || x.isEmpty())) { - return defaultValue; - } else { - if (profile2.profile(x == RRuntime.STRING_NA)) { - return RRuntime.INT_NA; - } else { - return (int) x.charAt(0); - } - } - }); + public static <T> PipelineStep<T, Byte> asLogical() { + return new CoercionStep<>(RType.Logical, false); } - @Override - public <T> ValuePredicateArgumentMapper<T, RNull> nullConstant() { - return ValuePredicateArgumentMapper.fromLambda(x -> RNull.instance); + public static <T> PipelineStep<T, RAbstractLogicalVector> asLogicalVector() { + return new CoercionStep<>(RType.Logical, true); } - @Override - public ValuePredicateArgumentMapper<String, String> constant(String s) { - return ValuePredicateArgumentMapper.<String, String> fromLambda((String x) -> s); + public static <T> PipelineStep<T, RAbstractLogicalVector> asLogicalVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { + return new CoercionStep<>(RType.Logical, true, preserveNames, preserveDimensions, preserveAttributes, false); } - @Override - public ValuePredicateArgumentMapper<Integer, Integer> constant(int i) { - return ValuePredicateArgumentMapper.fromLambda(x -> i); - } - - @Override - public ValuePredicateArgumentMapper<Double, Double> constant(double d) { - return ValuePredicateArgumentMapper.fromLambda(x -> d); + public static PipelineStep<Byte, Boolean> asBoolean() { + return map(toBoolean()); } - @Override - public ValuePredicateArgumentMapper<Byte, Byte> constant(byte l) { - return ValuePredicateArgumentMapper.fromLambda(x -> l); + public static <T> PipelineStep<T, RAbstractVector> asVector() { + return new CoercionStep<>(RType.Any, /* vectorCoercion: */true); } - @Override - public <T> ArgumentMapper<T, T> defaultValue(T defVal) { - - assert (defVal != null); - - return new ArgumentMapper<T, T>() { - - final ConditionProfile profile = ConditionProfile.createBinaryProfile(); - - @Override - public T map(T arg) { - if (profile.profile(arg == RNull.instance || arg == null)) { - return defVal; - } else { - return arg; - } - } - - }; + public static <T> PipelineStep<T, RAbstractVector> asVector(boolean preserveNonVector) { + return new CoercionStep<>(RType.Any, true, false, false, false, preserveNonVector); } - } - - public static final class Predef { - - private static PredefFilters predefFilters = new DefaultPredefFilters(); - private static PredefMappers predefMappers = new DefaultPredefMappers(); /** - * Invoked from tests only. - * - * @param pf + * Version of {@code findFirst} step that can be used in {@code chain}, must be followed by + * call for {@code xyzElement()}. */ - public static void setPredefFilters(PredefFilters pf) { - predefFilters = pf; + public static <V extends RAbstractVector> FindFirstNodeBuilder findFirst(RBaseNode callObj, RError.Message message, Object... messageArgs) { + return new FindFirstNodeBuilder(callObj, message, messageArgs); } /** - * Invoked from tests only. - * - * @param pm + * Version of {@code findFirst} step that can be used in {@code chain}, must be followed by + * call for {@code xyzElement()}. */ - public static void setPredefMappers(PredefMappers pm) { - predefMappers = pm; - } - - private static PredefFilters predefFilters() { - return predefFilters; - } - - private static PredefMappers predefMappers() { - return predefMappers; - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> mustBe(ArgumentFilter<?, ?> argFilter, RBaseNode callObj, boolean boxPrimitives, RError.Message message, Object... messageArgs) { - return phaseBuilder -> FilterNodeGen.create(argFilter, false, callObj, message, messageArgs, boxPrimitives); + public static <V extends RAbstractVector> FindFirstNodeBuilder findFirst(RError.Message message, Object... messageArgs) { + return new FindFirstNodeBuilder(null, message, messageArgs); } - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> mustBe(ArgumentFilter<?, ?> argFilter, boolean boxPrimitives) { - return phaseBuilder -> FilterNodeGen.create(argFilter, false, phaseBuilder.state().defaultError().callObj, phaseBuilder.state().defaultError().message, - phaseBuilder.state().defaultError().args, boxPrimitives); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> shouldBe(ArgumentFilter<?, ?> argFilter, RBaseNode callObj, boolean boxPrimitives, RError.Message message, Object... messageArgs) { - return phaseBuilder -> FilterNodeGen.create(argFilter, true, callObj, message, messageArgs, boxPrimitives); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> shouldBe(ArgumentFilter<?, ?> argFilter, boolean boxPrimitives) { - return phaseBuilder -> FilterNodeGen.create(argFilter, true, phaseBuilder.state().defaultError().callObj, phaseBuilder.state().defaultError().message, - phaseBuilder.state().defaultError().args, boxPrimitives); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> map(ArgumentMapper<?, ?> mapper) { - return phaseBuilder -> MapNodeGen.create(mapper); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> mapIf(ArgumentFilter<?, ?> filter, Function<ArgCastBuilder<T, ?>, CastNode> trueBranchFactory, - Function<ArgCastBuilder<T, ?>, CastNode> falseBranchFactory) { - return phaseBuilder -> ConditionalMapNodeGen.create(filter, trueBranchFactory.apply(phaseBuilder), falseBranchFactory.apply(phaseBuilder)); - } - - public static <T> ChainBuilder<T> chain(CastNode firstCast) { - return new ChainBuilder<>(pb -> firstCast); - } - - public static <T> ChainBuilder<T> chain(Function<ArgCastBuilder<T, ?>, CastNode> firstCastNodeFactory) { - return new ChainBuilder<>(firstCastNodeFactory); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asInteger() { - return phaseBuilder -> CastIntegerBaseNodeGen.create(false, false, false); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asIntegerVector() { - return phaseBuilder -> CastIntegerNodeGen.create(false, false, false); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asIntegerVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - return phaseBuilder -> CastIntegerNodeGen.create(preserveNames, preserveDimensions, preserveAttributes); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asDouble() { - return phaseBuilder -> CastDoubleBaseNodeGen.create(false, false, false); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asDoubleVector() { - return phaseBuilder -> CastDoubleNodeGen.create(false, false, false); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asDoubleVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - return phaseBuilder -> CastDoubleNodeGen.create(preserveNames, preserveDimensions, preserveAttributes); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asString() { - return phaseBuilder -> CastStringBaseNodeGen.create(false, false, false); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asStringVector() { - return phaseBuilder -> CastStringNodeGen.create(false, false, false, false); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asStringVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - return phaseBuilder -> CastStringNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, false); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asLogical() { - return phaseBuilder -> CastLogicalBaseNodeGen.create(false, false, false); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asLogicalVector() { - return phaseBuilder -> CastLogicalNodeGen.create(false, false, false); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asLogicalVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - return phaseBuilder -> CastLogicalNodeGen.create(preserveNames, preserveDimensions, preserveAttributes); - } - - public static <T> FindFirstNodeBuilder<T> findFirst(RBaseNode callObj, RError.Message message, Object... messageArgs) { - return new FindFirstNodeBuilder<>(callObj, message, messageArgs); - } - - public static <T> FindFirstNodeBuilder<T> findFirst(RError.Message message, Object... messageArgs) { - return new FindFirstNodeBuilder<>(null, message, messageArgs); - } - - public static <T> FindFirstNodeBuilder<T> findFirst() { - return new FindFirstNodeBuilder<>(null, null, null); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> notNA(RBaseNode callObj, RError.Message message, Object... messageArgs) { - return phaseBuilder -> NonNANodeGen.create(callObj, message, messageArgs, null); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> notNA(RError.Message message, Object... messageArgs) { - return phaseBuilder -> NonNANodeGen.create(null, message, messageArgs, null); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> notNA(T naReplacement, RError.Message message, Object... messageArgs) { - return phaseBuilder -> NonNANodeGen.create(null, message, messageArgs, naReplacement); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> notNA(T naReplacement) { - return phaseBuilder -> NonNANodeGen.create(naReplacement); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> notNA() { - return phaseBuilder -> NonNANodeGen.create(phaseBuilder.state().defaultError().callObj, phaseBuilder.state().defaultError().message, phaseBuilder.state().defaultError().args, null); - } - - public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asBoolean() { - return map(toBoolean()); - } - - public static <T> ValuePredicateArgumentFilter<T> sameAs(T x) { - return predefFilters().sameAs(x); - } - - public static <T> ValuePredicateArgumentFilter<T> equalTo(T x) { - return predefFilters().equalTo(x); - } - - public static <T, R extends T> TypePredicateArgumentFilter<T, R> nullValue() { - return predefFilters().nullValue(); - } - - public static <T extends RAbstractVector> VectorPredicateArgumentFilter<T> notEmpty() { - return predefFilters().notEmpty(); - } - - public static <T extends RAbstractVector> VectorPredicateArgumentFilter<T> singleElement() { - return predefFilters().singleElement(); - } - - public static <T extends RAbstractVector, R extends T> VectorPredicateArgumentFilter<T> size(int s) { - return predefFilters().size(s); - } - - public static VectorPredicateArgumentFilter<RAbstractStringVector> elementAt(int index, String value) { - return predefFilters().elementAt(index, value); - } - - public static VectorPredicateArgumentFilter<RAbstractIntVector> elementAt(int index, int value) { - return predefFilters().elementAt(index, value); - } - - public static VectorPredicateArgumentFilter<RAbstractDoubleVector> elementAt(int index, double value) { - return predefFilters().elementAt(index, value); - } - - public static VectorPredicateArgumentFilter<RAbstractComplexVector> elementAt(int index, RComplex value) { - return predefFilters().elementAt(index, value); - } - - public static VectorPredicateArgumentFilter<RAbstractLogicalVector> elementAt(int index, byte value) { - return predefFilters().elementAt(index, value); - } - - public static ValuePredicateArgumentFilter<Boolean> trueValue() { - return predefFilters().trueValue(); - } - - public static ValuePredicateArgumentFilter<Boolean> falseValue() { - return predefFilters().falseValue(); - } - - public static ValuePredicateArgumentFilter<Byte> logicalTrue() { - return predefFilters().logicalTrue(); - } - - public static ValuePredicateArgumentFilter<Byte> logicalFalse() { - return predefFilters().logicalFalse(); - } - - public static ValuePredicateArgumentFilter<Integer> intNA() { - return predefFilters().intNA(); - } - - public static ArgumentValueFilter<Integer> notIntNA() { - return predefFilters().intNA().not(); - } - - public static ValuePredicateArgumentFilter<Byte> logicalNA() { - return predefFilters().logicalNA(); - } - - public static ArgumentValueFilter<Byte> notLogicalNA() { - return predefFilters().logicalNA().not(); - } - - public static ValuePredicateArgumentFilter<Double> doubleNA() { - return predefFilters().doubleNA(); - } - - public static ArgumentValueFilter<Double> notDoubleNA() { - return predefFilters().doubleNA().not(); - } - - public static ValuePredicateArgumentFilter<String> stringNA() { - return predefFilters().stringNA(); - } - - public static ArgumentValueFilter<String> notStringNA() { - return predefFilters().stringNA().not(); - } - - public static ValuePredicateArgumentFilter<Integer> eq(int x) { - return predefFilters().eq(x); - } - - public static ValuePredicateArgumentFilter<Double> eq(double x) { - return predefFilters().eq(x); - } - - public static ArgumentValueFilter<Integer> neq(int x) { - return predefFilters().eq(x).not(); - } - - public static ArgumentValueFilter<Double> neq(double x) { - return predefFilters().eq(x).not(); - } - - public static ValuePredicateArgumentFilter<Integer> gt(int x) { - return predefFilters().gt(x); - } - - public static ValuePredicateArgumentFilter<Double> gt(double x) { - return predefFilters().gt(x); - } - - public static ValuePredicateArgumentFilter<Integer> gte(int x) { - return predefFilters().gt(x - 1); - } - - public static ValuePredicateArgumentFilter<Double> gte(double x) { - return predefFilters().gte(x); - } - - public static ValuePredicateArgumentFilter<Integer> lt(int x) { - return predefFilters().lt(x); - } - - public static ValuePredicateArgumentFilter<Double> lt(double x) { - return predefFilters().lt(x); - } - - public static ValuePredicateArgumentFilter<Integer> lte(int x) { - return predefFilters().lt(x + 1); - } - - public static ValuePredicateArgumentFilter<Double> lte(double x) { - return predefFilters().lte(x); - } - - public static ValuePredicateArgumentFilter<String> length(int l) { - return predefFilters().length(l); - } - - public static ValuePredicateArgumentFilter<String> isEmpty() { - return predefFilters().lengthLt(1); - } - - public static ValuePredicateArgumentFilter<String> lengthGt(int l) { - return predefFilters().lengthGt(l); - } - - public static ValuePredicateArgumentFilter<String> lengthGte(int l) { - return predefFilters().lengthGt(l - 1); - } - - public static ValuePredicateArgumentFilter<String> lengthLt(int l) { - return predefFilters().lengthLt(l); - } - - public static ValuePredicateArgumentFilter<String> lengthLte(int l) { - return predefFilters().lengthLt(l + 1); - } - - public static ValuePredicateArgumentFilter<Integer> gt0() { - return predefFilters().gt(0); - } - - public static ValuePredicateArgumentFilter<Integer> gte0() { - return predefFilters().gt(-1); - } - - public static ValuePredicateArgumentFilter<Integer> gt1() { - return predefFilters().gt(1); - } - - public static ValuePredicateArgumentFilter<Integer> gte1() { - return predefFilters().gt(0); - } - - public static <R> TypePredicateArgumentFilter<Object, R> instanceOf(Class<R> cls) { - return predefFilters().instanceOf(cls); - } - - public static <R extends RAbstractIntVector> TypePredicateArgumentFilter<Object, R> integerValue() { - return predefFilters().integerValue(); - } - - public static <R extends RAbstractStringVector> TypePredicateArgumentFilter<Object, R> stringValue() { - return predefFilters().stringValue(); - } - - public static <R extends RAbstractDoubleVector> TypePredicateArgumentFilter<Object, R> doubleValue() { - return predefFilters().doubleValue(); - } - - public static <R extends RAbstractLogicalVector> TypePredicateArgumentFilter<Object, R> logicalValue() { - return predefFilters().logicalValue(); - } - - public static <R extends RAbstractComplexVector> TypePredicateArgumentFilter<Object, R> complexValue() { - return predefFilters().complexValue(); - } - - public static ArgumentTypeFilter<Object, Object> numericValue() { - return integerValue().or(doubleValue()).or(logicalValue()); - } - - public static TypePredicateArgumentFilter<Object, String> scalarStringValue() { - return predefFilters().scalarStringValue(); - } - - public static TypePredicateArgumentFilter<Object, Integer> scalarIntegerValue() { - return predefFilters().scalarIntegerValue(); - } - - public static TypePredicateArgumentFilter<Object, Double> scalarDoubleValue() { - return predefFilters().scalarDoubleValue(); - } - - public static TypePredicateArgumentFilter<Object, Byte> scalarLogicalValue() { - return predefFilters().scalarLogicalValue(); - } - - public static TypePredicateArgumentFilter<Object, RComplex> scalarComplexValue() { - return predefFilters().scalarComplexValue(); - } - - public static TypePredicateArgumentFilter<Object, RMissing> missingValue() { - return predefFilters().missingValue(); - } - - public static ValuePredicateArgumentMapper<Byte, Boolean> toBoolean() { - return predefMappers().toBoolean(); - } - - public static ValuePredicateArgumentMapper<String, Integer> charAt0(int defaultValue) { - return predefMappers().charAt0(defaultValue); - } - - public static <T> ValuePredicateArgumentMapper<T, RNull> nullConstant() { - return predefMappers().nullConstant(); - } - - public static ValuePredicateArgumentMapper<String, String> constant(String s) { - return predefMappers().constant(s); - } - - public static ValuePredicateArgumentMapper<Integer, Integer> constant(int i) { - return predefMappers().constant(i); - } - - public static ValuePredicateArgumentMapper<Double, Double> constant(double d) { - return predefMappers().constant(d); - } - - public static ValuePredicateArgumentMapper<Byte, Byte> constant(byte l) { - return predefMappers().constant(l); - } - - public static <T> ArgumentMapper<T, T> defaultValue(T defVal) { - return predefMappers().defaultValue(defVal); - } - - } - - @SuppressWarnings("unchecked") - interface ArgCastBuilder<T, THIS> { - - ArgCastBuilderState state(); - - default CastBuilder builder() { - return state().castBuilder(); + /** + * 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() { + return new FindFirstNodeBuilder(null, null, null); } - default THIS defaultError(RBaseNode callObj, RError.Message message, Object... args) { - state().setDefaultError(callObj, message, args); - return (THIS) this; + public static <T> PipelineStep<T, T> notNA(RBaseNode callObj, RError.Message message, Object... messageArgs) { + return notNA(null, callObj, message, messageArgs); } - default THIS defaultError(RError.Message message, Object... args) { - state().setDefaultError(message, args); - return (THIS) this; + public static <T> PipelineStep<T, T> notNA(RError.Message message, Object... messageArgs) { + return notNA(null, null, message, messageArgs); } - default THIS defaultWarning(RBaseNode callObj, RError.Message message, Object... args) { - state().setDefaultWarning(callObj, message, args); - return (THIS) this; + 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)); } - default THIS defaultWarning(RError.Message message, Object... args) { - state().setDefaultWarning(message, args); - return (THIS) this; + public static <T> PipelineStep<T, T> notNA(T naReplacement, RError.Message message, Object... messageArgs) { + return notNA(naReplacement, null, message, messageArgs); } - default THIS shouldBe(ArgumentFilter<? super T, ?> argFilter, RError.Message message, Object... messageArgs) { - state().castBuilder().insert(state().index(), FilterNodeGen.create(argFilter, true, null, message, messageArgs, state().boxPrimitives)); - return (THIS) this; + public static <T> PipelineStep<T, T> notNA(T naReplacement) { + return new NotNAStep<>(naReplacement, null); } - default THIS shouldBe(ArgumentFilter<? super T, ?> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) { - state().castBuilder().insert(state().index(), FilterNodeGen.create(argFilter, true, callObj, message, messageArgs, state().boxPrimitives)); - return (THIS) this; + public static <T> PipelineStep<T, T> notNA() { + return new NotNAStep<>(null, null); } - default THIS shouldBe(ArgumentFilter<? super T, ?> argFilter) { - return shouldBe(argFilter, state().defaultWarning().message, state().defaultWarning().args); + public static <T> CompareFilter<T> sameAs(T x) { + return new CompareFilter<>(CompareFilter.SAME, new CompareFilter.ScalarValue(x, RType.Any)); } - default <R, THAT extends ArgCastBuilder<R, THAT>> THAT alias(Function<THIS, THAT> aliaser) { - return aliaser.apply((THIS) this); + public static <T> CompareFilter<T> equalTo(T x) { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ScalarValue(x, RType.Any)); } - } - - interface ArgCastBuilderFactory { - - InitialPhaseBuilder<Object> newInitialPhaseBuilder(); - - <T> InitialPhaseBuilder<T> newInitialPhaseBuilder(ArgCastBuilder<?, ?> currentBuilder); - - <T extends RAbstractVector, S> CoercedPhaseBuilder<T, S> newCoercedPhaseBuilder(ArgCastBuilder<?, ?> currentBuilder, Class<?> elementClass); - - <T> HeadPhaseBuilder<T> newHeadPhaseBuilder(ArgCastBuilder<?, ?> currentBuilder); - - } - - static class DefaultError { - final RBaseNode callObj; - final RError.Message message; - final Object[] args; - - DefaultError(RBaseNode callObj, RError.Message message, Object... args) { - this.callObj = callObj; - this.message = message; - this.args = args; + public static <T extends RAbstractVector> CompareFilter<T> notEmpty() { + return new CompareFilter<>(CompareFilter.GT, new CompareFilter.VectorSize(0)); } - } - - static class ArgCastBuilderState { - private final DefaultError defaultDefaultError; - - private final int argumentIndex; - private final String argumentName; - final ArgCastBuilderFactory factory; - private final CastBuilder cb; - final boolean boxPrimitives; - private DefaultError defError; - private DefaultError defWarning; - - ArgCastBuilderState(int argumentIndex, String argumentName, ArgCastBuilderFactory fact, CastBuilder cb, boolean boxPrimitives) { - this.argumentIndex = argumentIndex; - this.argumentName = argumentName; - this.factory = fact; - this.cb = cb; - this.boxPrimitives = boxPrimitives; - this.defaultDefaultError = new DefaultError(null, RError.Message.INVALID_ARGUMENT, argumentName); + public static <T extends RAbstractVector> CompareFilter<T> singleElement() { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.VectorSize(1)); } - ArgCastBuilderState(ArgCastBuilderState prevState, boolean boxPrimitives) { - this.argumentIndex = prevState.argumentIndex; - this.argumentName = prevState.argumentName; - this.factory = prevState.factory; - this.cb = prevState.cb; - this.boxPrimitives = boxPrimitives; - this.defError = prevState.defError; - this.defWarning = prevState.defWarning; - this.defaultDefaultError = new DefaultError(null, RError.Message.INVALID_ARGUMENT, argumentName); + public static <T extends RAbstractVector> CompareFilter<T> size(int s) { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.VectorSize(s)); } - public int index() { - return argumentIndex; + public static <T extends RAbstractStringVector> CompareFilter<T> elementAt(int index, String value) { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ElementAt(index, value, RType.Character)); } - public String name() { - return argumentName; + public static <T extends RAbstractIntVector> CompareFilter<T> elementAt(int index, int value) { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ElementAt(index, value, RType.Integer)); } - public CastBuilder castBuilder() { - return cb; + public static <T extends RAbstractDoubleVector> CompareFilter<T> elementAt(int index, double value) { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ElementAt(index, value, RType.Double)); } - boolean isDefaultErrorDefined() { - return defError != null; + public static <T extends RAbstractComplexVector> CompareFilter<T> elementAt(int index, RComplex value) { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ElementAt(index, value, RType.Complex)); } - boolean isDefaultWarningDefined() { - return defWarning != null; + public static <T extends RAbstractLogicalVector> CompareFilter<T> elementAt(int index, byte value) { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ElementAt(index, value, RType.Logical)); } - void setDefaultError(RBaseNode callObj, RError.Message message, Object... args) { - defError = new DefaultError(callObj, message, args); + public static <T extends RAbstractVector> MatrixFilter<T> matrix() { + return MatrixFilter.isMatrixFilter(); } - void setDefaultError(RError.Message message, Object... args) { - defError = new DefaultError(null, message, args); + public static <T extends RAbstractVector> MatrixFilter<T> squareMatrix() { + return MatrixFilter.isSquareMatrixFilter(); } - void setDefaultWarning(RBaseNode callObj, RError.Message message, Object... args) { - defWarning = new DefaultError(callObj, message, args); + public static <T extends RAbstractVector> CompareFilter<T> dimEq(int dim, int x) { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.Dim(dim, x)); } - void setDefaultWarning(RError.Message message, Object... args) { - defWarning = new DefaultError(null, message, args); + public static <T extends RAbstractVector> CompareFilter<T> dimGt(int dim, int x) { + return new CompareFilter<>(CompareFilter.GT, new CompareFilter.Dim(dim, x)); } - DefaultError defaultError() { - return defError == null ? defaultDefaultError : defError; + public static CompareFilter<Byte> logicalTrue() { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ScalarValue(RRuntime.LOGICAL_TRUE, RType.Logical)); } - DefaultError defaultError(RBaseNode callObj, RError.Message defaultDefaultMessage, Object... defaultDefaultArgs) { - return defError == null ? new DefaultError(callObj, defaultDefaultMessage, defaultDefaultArgs) : defError; + public static CompareFilter<Byte> logicalFalse() { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ScalarValue(RRuntime.LOGICAL_FALSE, RType.Logical)); } - DefaultError defaultError(RError.Message defaultDefaultMessage, Object... defaultDefaultArgs) { - return defError == null ? new DefaultError(null, defaultDefaultMessage, defaultDefaultArgs) : defError; + public static CompareFilter<Integer> intNA() { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.NATest(RType.Integer)); } - DefaultError defaultWarning() { - return defWarning == null ? defaultDefaultError : defWarning; + public static NotFilter<Integer> notIntNA() { + return new NotFilter<>(intNA()); } - DefaultError defaultWarning(RBaseNode callObj, RError.Message defaultDefaultMessage, Object... defaultDefaultArgs) { - return defWarning == null ? new DefaultError(callObj, defaultDefaultMessage, defaultDefaultArgs) : defWarning; + public static CompareFilter<Byte> logicalNA() { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.NATest(RType.Logical)); } - DefaultError defaultWarning(RError.Message defaultDefaultMessage, Object... defaultDefaultArgs) { - return defWarning == null ? new DefaultError(null, defaultDefaultMessage, defaultDefaultArgs) : defWarning; + public static NotFilter<Byte> notLogicalNA() { + return new NotFilter<>(logicalNA()); } - void mustBe(ArgumentFilter<?, ?> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) { - castBuilder().insert(index(), FilterNodeGen.create(argFilter, false, callObj, message, messageArgs, boxPrimitives)); + public static CompareFilter<Double> doubleNA() { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.NATest(RType.Double)); } - void mustBe(ArgumentFilter<?, ?> argFilter) { - mustBe(argFilter, defaultError().callObj, defaultError().message, defaultError().args); + public static NotFilter<Double> notDoubleNA() { + return new NotFilter<>(doubleNA()); } - void shouldBe(ArgumentFilter<?, ?> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) { - castBuilder().insert(index(), FilterNodeGen.create(argFilter, true, callObj, message, messageArgs, boxPrimitives)); + public static CompareFilter<String> stringNA() { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.NATest(RType.Character)); } - void shouldBe(ArgumentFilter<?, ?> argFilter) { - shouldBe(argFilter, defaultWarning().callObj, defaultWarning().message, defaultWarning().args); + public static NotFilter<String> notStringNA() { + return new NotFilter<>(stringNA()); } - } - - abstract class ArgCastBuilderBase<T, THIS> implements ArgCastBuilder<T, THIS> { - - private final ArgCastBuilderState st; - - ArgCastBuilderBase(ArgCastBuilderState state) { - this.st = state; + public static CompareFilter<RComplex> complexNA() { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.NATest(RType.Complex)); } - @Override - public ArgCastBuilderState state() { - return st; + public static NotFilter<RComplex> notComplexNA() { + return new NotFilter<>(complexNA()); } - } - - public interface InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilder<T>> { - default <S> InitialPhaseBuilder<S> mustBe(ArgumentFilter<? super T, S> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) { - state().mustBe(argFilter, callObj, message, messageArgs); - return state().factory.newInitialPhaseBuilder(this); + public static DoubleFilter isFractional() { + return DoubleFilter.IS_FRACTIONAL; } - default <S> InitialPhaseBuilder<S> mustBe(ArgumentFilter<? super T, S> argFilter, RError.Message message, Object... messageArgs) { - state().mustBe(argFilter, null, message, messageArgs); - return state().factory.newInitialPhaseBuilder(this); + public static DoubleFilter isFinite() { + return DoubleFilter.IS_FINITE; } - default <S> InitialPhaseBuilder<S> mustBe(ArgumentFilter<? super T, S> argFilter) { - return mustBe(argFilter, state().defaultError().message, state().defaultError().args); + public static CompareFilter<Integer> eq(int x) { + return new CompareFilter<>(CompareFilter.SAME, new CompareFilter.ScalarValue(x, RType.Integer)); } - default <S> InitialPhaseBuilder<S> mustBe(Class<S> cls, RBaseNode callObj, RError.Message message, Object... messageArgs) { - mustBe(Predef.instanceOf(cls), callObj, message, messageArgs); - return state().factory.newInitialPhaseBuilder(this); + public static CompareFilter<Double> eq(double x) { + return new CompareFilter<>(CompareFilter.SAME, new CompareFilter.ScalarValue(x, RType.Double)); } - default <S> InitialPhaseBuilder<S> mustBe(Class<S> cls, RError.Message message, Object... messageArgs) { - mustBe(Predef.instanceOf(cls), message, messageArgs); - return state().factory.newInitialPhaseBuilder(this); + public static CompareFilter<Byte> eq(byte x) { + return new CompareFilter<>(CompareFilter.SAME, new CompareFilter.ScalarValue(x, RType.Logical)); } - default <S> InitialPhaseBuilder<S> mustBe(Class<S> cls) { - mustBe(Predef.instanceOf(cls)); - return state().factory.newInitialPhaseBuilder(this); + public static CompareFilter<String> eq(String x) { + return new CompareFilter<>(CompareFilter.SAME, new CompareFilter.ScalarValue(x, RType.Character)); } - default <S> InitialPhaseBuilder<S> shouldBe(Class<S> cls, RBaseNode callObj, RError.Message message, Object... messageArgs) { - shouldBe(Predef.instanceOf(cls), callObj, message, messageArgs); - return state().factory.newInitialPhaseBuilder(this); + public static NotFilter<Integer> neq(int x) { + return new NotFilter<>(eq(x)); } - default <S> InitialPhaseBuilder<S> shouldBe(Class<S> cls, RError.Message message, Object... messageArgs) { - shouldBe(Predef.instanceOf(cls), message, messageArgs); - return state().factory.newInitialPhaseBuilder(this); + public static NotFilter<Double> neq(double x) { + return new NotFilter<>(eq(x)); } - default <S> InitialPhaseBuilder<S> shouldBe(Class<S> cls) { - shouldBe(Predef.instanceOf(cls)); - return state().factory.newInitialPhaseBuilder(this); + public static CompareFilter<Integer> gt(int x) { + return new CompareFilter<>(CompareFilter.GT, new CompareFilter.ScalarValue(x, RType.Integer)); } - default <S> InitialPhaseBuilder<S> map(ArgumentMapper<T, S> mapFn) { - state().castBuilder().insert(state().index(), MapNodeGen.create(mapFn)); - return state().factory.newInitialPhaseBuilder(this); + public static CompareFilter<Double> gt(double x) { + return new CompareFilter<>(CompareFilter.GT, new CompareFilter.ScalarValue(x, RType.Double)); } - @SuppressWarnings("overloads") - default <S, R> InitialPhaseBuilder<Object> mapIf(ArgumentFilter<? super T, S> argFilter, ArgumentMapper<S, R> trueBranchMapper) { - state().castBuilder().insert(state().index(), ConditionalMapNodeGen.create(argFilter, MapNodeGen.create(trueBranchMapper), null)); - - return state().factory.newInitialPhaseBuilder(this); + public static CompareFilter<Integer> gte(int x) { + return new CompareFilter<>(CompareFilter.GE, new CompareFilter.ScalarValue(x, RType.Integer)); } - default <S, R> InitialPhaseBuilder<Object> mapIf(ArgumentFilter<? super T, S> argFilter, CastNode trueBranchNode) { - state().castBuilder().insert(state().index(), ConditionalMapNodeGen.create(argFilter, trueBranchNode, null)); - - return state().factory.newInitialPhaseBuilder(this); + public static CompareFilter<Double> gte(double x) { + return new CompareFilter<>(CompareFilter.GE, new CompareFilter.ScalarValue(x, RType.Double)); } - @SuppressWarnings("overloads") - default <S, R> InitialPhaseBuilder<Object> mapIf(ArgumentFilter<? super T, S> argFilter, Function<ArgCastBuilder<T, ?>, CastNode> trueBranchNode) { - state().castBuilder().insert(state().index(), ConditionalMapNodeGen.create(argFilter, trueBranchNode.apply(this), null)); - - return state().factory.newInitialPhaseBuilder(this); + public static CompareFilter<Integer> lt(int x) { + return new CompareFilter<>(CompareFilter.LT, new CompareFilter.ScalarValue(x, RType.Integer)); } - @SuppressWarnings("overloads") - default <S, R> InitialPhaseBuilder<Object> mapIf(ArgumentFilter<? super T, S> argFilter, ArgumentMapper<S, R> trueBranchMapper, ArgumentMapper<T, T> falseBranchMapper) { - state().castBuilder().insert( - state().index(), - ConditionalMapNodeGen.create(argFilter, MapNodeGen.create(trueBranchMapper), - MapNodeGen.create(falseBranchMapper))); - - return state().factory.newInitialPhaseBuilder(this); + public static CompareFilter<Double> lt(double x) { + return new CompareFilter<>(CompareFilter.LT, new CompareFilter.ScalarValue(x, RType.Double)); } - default <S, R> InitialPhaseBuilder<Object> mapIf(ArgumentFilter<? super T, S> argFilter, CastNode trueBranchNode, CastNode falseBranchNode) { - state().castBuilder().insert(state().index(), ConditionalMapNodeGen.create(argFilter, trueBranchNode, falseBranchNode)); - - return state().factory.newInitialPhaseBuilder(this); + public static CompareFilter<Integer> lte(int x) { + return new CompareFilter<>(CompareFilter.LE, new CompareFilter.ScalarValue(x, RType.Integer)); } - @SuppressWarnings("overloads") - default <S, R> InitialPhaseBuilder<Object> mapIf(ArgumentFilter<? super T, S> argFilter, Function<ArgCastBuilder<T, ?>, CastNode> trueBranchNodeFactory, - Function<ArgCastBuilder<T, ?>, CastNode> falseBranchNodeFactory) { - state().castBuilder().insert(state().index(), ConditionalMapNodeGen.create(argFilter, trueBranchNodeFactory.apply(this), falseBranchNodeFactory.apply(this))); - - return state().factory.newInitialPhaseBuilder(this); + public static CompareFilter<Double> lte(double x) { + return new CompareFilter<>(CompareFilter.LE, new CompareFilter.ScalarValue(x, RType.Double)); } - default InitialPhaseBuilder<T> notNA(RBaseNode callObj, RError.Message message, Object... messageArgs) { - state().castBuilder().insert(state().index(), NonNANodeGen.create(callObj, message, messageArgs, null)); - return this; + public static CompareFilter<String> length(int l) { + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.StringLength(l)); } - default InitialPhaseBuilder<T> notNA(RError.Message message, Object... messageArgs) { - state().castBuilder().insert(state().index(), NonNANodeGen.create(null, message, messageArgs, null)); - return this; + public static CompareFilter<String> isEmpty() { + return length(0); } - default InitialPhaseBuilder<T> notNA(T naReplacement, RBaseNode callObj, RError.Message message, Object... messageArgs) { - state().castBuilder().insert(state().index(), NonNANodeGen.create(callObj, message, messageArgs, naReplacement)); - return this; + public static CompareFilter<String> lengthGt(int l) { + return new CompareFilter<>(CompareFilter.GT, new CompareFilter.StringLength(l)); } - default InitialPhaseBuilder<T> notNA(T naReplacement, RError.Message message, Object... messageArgs) { - state().castBuilder().insert(state().index(), NonNANodeGen.create(null, message, messageArgs, naReplacement)); - return this; + public static CompareFilter<String> lengthGte(int l) { + return new CompareFilter<>(CompareFilter.GE, new CompareFilter.StringLength(l)); } - default InitialPhaseBuilder<T> notNA(T naReplacement) { - state().castBuilder().insert(state().index(), NonNANodeGen.create(naReplacement)); - return this; + public static CompareFilter<String> lengthLt(int l) { + return new CompareFilter<>(CompareFilter.LT, new CompareFilter.StringLength(l)); } - default InitialPhaseBuilder<T> notNA() { - state().castBuilder().insert(state().index(), NonNANodeGen.create(state().defaultError().callObj, state().defaultError().message, state().defaultError().args, null)); - return this; + public static CompareFilter<String> lengthLte(int l) { + return new CompareFilter<>(CompareFilter.LE, new CompareFilter.StringLength(l)); } - default CoercedPhaseBuilder<RAbstractIntVector, Integer> asIntegerVector(boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { - state().castBuilder().toInteger(state().index(), preserveNames, dimensionsPreservation, attrPreservation); - return state().factory.newCoercedPhaseBuilder(this, Integer.class); + public static CompareFilter<Integer> gt0() { + return gt(0); } - default CoercedPhaseBuilder<RAbstractIntVector, Integer> asIntegerVector() { - return asIntegerVector(false, false, false); + public static CompareFilter<Integer> gte0() { + return gte(0); } - default CoercedPhaseBuilder<RAbstractDoubleVector, Double> asDoubleVector(boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { - state().castBuilder().toDouble(state().index(), preserveNames, dimensionsPreservation, attrPreservation); - return state().factory.newCoercedPhaseBuilder(this, Double.class); + public static CompareFilter<Integer> gt1() { + return gt(1); } - default CoercedPhaseBuilder<RAbstractDoubleVector, Double> asDoubleVector() { - return asDoubleVector(false, false, false); + public static CompareFilter<Integer> gte1() { + return gte(1); } - default CoercedPhaseBuilder<RAbstractLogicalVector, Byte> asLogicalVector() { - state().castBuilder().toLogical(state().index()); - return state().factory.newCoercedPhaseBuilder(this, Byte.class); + public static <R> TypeFilter<Object, R> instanceOf(Class<R> cls) { + return new TypeFilter<>(x -> cls.isInstance(x), cls); } - default CoercedPhaseBuilder<RAbstractStringVector, String> asStringVector() { - state().castBuilder().toCharacter(state().index()); - return state().factory.newCoercedPhaseBuilder(this, String.class); + public static <R extends RAbstractIntVector> Filter<Object, R> integerValue() { + return new RTypeFilter<>(RType.Integer); } - default CoercedPhaseBuilder<RAbstractVector, Object> asVector() { - state().castBuilder().toVector(state().index()); - return state().factory.newCoercedPhaseBuilder(this, Object.class); + public static <R extends RAbstractStringVector> Filter<Object, R> stringValue() { + return new RTypeFilter<>(RType.Character); } - default HeadPhaseBuilder<RAttributable> asAttributable(boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { - state().castBuilder().toAttributable(state().index(), preserveNames, dimensionsPreservation, attrPreservation); - return state().factory.newHeadPhaseBuilder(this); + public static <R extends RAbstractDoubleVector> Filter<Object, R> doubleValue() { + return new RTypeFilter<>(RType.Double); } - } - - public interface CoercedPhaseBuilder<T extends RAbstractVector, S> extends ArgCastBuilder<T, CoercedPhaseBuilder<T, S>> { - - /** - * The inserted cast node returns the default value if the input vector is empty. It also - * reports the warning message. - */ - default HeadPhaseBuilder<S> findFirst(S defaultValue, RError.Message message, Object... messageArgs) { - state().castBuilder().insert(state().index(), FindFirstNodeGen.create(elementClass(), null, message, messageArgs, defaultValue)); - return state().factory.newHeadPhaseBuilder(this); + public static <R extends RAbstractLogicalVector> Filter<Object, R> logicalValue() { + return new RTypeFilter<>(RType.Logical); } - default HeadPhaseBuilder<S> findFirst(S defaultValue, RBaseNode callObj, RError.Message message, Object... messageArgs) { - state().castBuilder().insert(state().index(), FindFirstNodeGen.create(elementClass(), callObj, message, messageArgs, defaultValue)); - return state().factory.newHeadPhaseBuilder(this); + public static <R extends RAbstractComplexVector> Filter<Object, R> complexValue() { + return new RTypeFilter<>(RType.Complex); } - /** - * The inserted cast node raises an error if the input vector is empty. - */ - default HeadPhaseBuilder<S> findFirst(RError.Message message, Object... messageArgs) { - state().castBuilder().insert(state().index(), FindFirstNodeGen.create(elementClass(), null, message, messageArgs, null)); - return state().factory.newHeadPhaseBuilder(this); + public static <R extends RAbstractRawVector> Filter<Object, R> rawValue() { + return new RTypeFilter<>(RType.Raw); } - default HeadPhaseBuilder<S> findFirst(RBaseNode callObj, RError.Message message, Object... messageArgs) { - state().castBuilder().insert(state().index(), FindFirstNodeGen.create(elementClass(), callObj, message, messageArgs, null)); - return state().factory.newHeadPhaseBuilder(this); + public static <R> TypeFilter<Object, R> anyValue() { + return new TypeFilter<>(x -> true, Object.class); } - /** - * The inserted cast node raises the default error, if defined, or - * RError.Message.LENGTH_ZERO error if the input vector is empty. - */ - default HeadPhaseBuilder<S> findFirst() { - DefaultError err = state().isDefaultErrorDefined() ? state().defaultError() : new DefaultError(null, RError.Message.LENGTH_ZERO); - state().castBuilder().insert(state().index(), - FindFirstNodeGen.create(elementClass(), err.callObj, err.message, err.args, null)); - return state().factory.newHeadPhaseBuilder(this); + @SuppressWarnings({"rawtypes", "unchecked", "cast"}) + public static Filter<Object, RAbstractVector> numericValue() { + Filter f = integerValue().or(doubleValue()).or(logicalValue()); + return (Filter<Object, RAbstractVector>) f; } /** - * The inserted cast node returns the default value if the input vector is empty. It reports - * no warning message. + * Checks that the argument is a list or vector/scalar of type numeric, string, complex or + * raw. */ - default HeadPhaseBuilder<S> findFirst(S defaultValue) { - state().castBuilder().insert(state().index(), FindFirstNodeGen.create(elementClass(), defaultValue)); - return state().factory.newHeadPhaseBuilder(this); + @SuppressWarnings({"rawtypes", "unchecked", "cast"}) + public static Filter<Object, RAbstractVector> abstractVectorValue() { + Filter f = numericValue().or(stringValue()).or(complexValue()).or(rawValue()).or(instanceOf(RAbstractListVector.class)); + return (Filter<Object, RAbstractVector>) f; } - Class<?> elementClass(); - - default CoercedPhaseBuilder<T, S> mustBe(ArgumentFilter<? super T, ? extends T> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) { - state().mustBe(argFilter, callObj, message, messageArgs); - return this; - } - - default CoercedPhaseBuilder<T, S> mustBe(ArgumentFilter<? super T, ? extends T> argFilter, RError.Message message, Object... messageArgs) { - state().mustBe(argFilter, null, message, messageArgs); - return this; - } - - default CoercedPhaseBuilder<T, S> mustBe(ArgumentFilter<? super T, ? extends T> argFilter) { - return mustBe(argFilter, state().defaultError().message, state().defaultError().args); - } - - } - - public interface HeadPhaseBuilder<T> extends ArgCastBuilder<T, HeadPhaseBuilder<T>> { - - default <S> HeadPhaseBuilder<S> map(ArgumentMapper<T, S> mapFn) { - state().castBuilder().insert(state().index(), MapNodeGen.create(mapFn)); - return state().factory.newHeadPhaseBuilder(this); + public static Filter<Object, Integer> atomicIntegerValue() { + return new TypeFilter<>(x -> x instanceof String, String.class); } - default <S, R> HeadPhaseBuilder<Object> mapIf(ArgumentFilter<? super T, S> argFilter, ArgumentMapper<S, R> trueBranchMapper) { - state().castBuilder().insert(state().index(), ConditionalMapNodeGen.create(argFilter, MapNodeGen.create(trueBranchMapper), null)); - - return state().factory.newHeadPhaseBuilder(this); + public static Filter<Object, Byte> atomicLogicalValue() { + return new TypeFilter<>(x -> x instanceof Byte, Byte.class); } - default <S, R> HeadPhaseBuilder<Object> mapIf(ArgumentFilter<? super T, S> argFilter, CastNode trueBranchNode) { - state().castBuilder().insert(state().index(), ConditionalMapNodeGen.create(argFilter, trueBranchNode, null)); - - return state().factory.newHeadPhaseBuilder(this); + public static MapByteToBoolean toBoolean() { + return MapByteToBoolean.INSTANCE; } - @SuppressWarnings("overloads") - default <S, R> HeadPhaseBuilder<Object> mapIf(ArgumentFilter<? super T, S> argFilter, ArgumentMapper<S, R> trueBranchMapper, ArgumentMapper<T, T> falseBranchMapper) { - state().castBuilder().insert( - state().index(), - ConditionalMapNodeGen.create(argFilter, MapNodeGen.create(trueBranchMapper), - MapNodeGen.create(falseBranchMapper))); - - return state().factory.newHeadPhaseBuilder(this); + public static MapDoubleToInt doubleToInt() { + return MapDoubleToInt.INSTANCE; } - @SuppressWarnings("overloads") - default <S, R> HeadPhaseBuilder<Object> mapIf(ArgumentFilter<? super T, S> argFilter, Function<ArgCastBuilder<T, ?>, CastNode> trueBranchNodeFactory, - Function<ArgCastBuilder<T, ?>, CastNode> falseBranchNodeFactory) { - state().castBuilder().insert(state().index(), ConditionalMapNodeGen.create(argFilter, trueBranchNodeFactory.apply(this), falseBranchNodeFactory.apply(this))); - - return state().factory.newHeadPhaseBuilder(this); + public static MapToCharAt charAt0(int defaultValue) { + return new MapToCharAt(0, defaultValue); } - default <S, R> HeadPhaseBuilder<Object> mapIf(ArgumentFilter<? super T, S> argFilter, CastNode trueBranchNode, CastNode falseBranchNode) { - state().castBuilder().insert(state().index(), ConditionalMapNodeGen.create(argFilter, trueBranchNode, falseBranchNode)); - - return state().factory.newHeadPhaseBuilder(this); + public static <T> MapToValue<T, RNull> nullConstant() { + return new MapToValue<>(RNull.instance); } - default <S> HeadPhaseBuilder<S> mustBe(ArgumentFilter<? super T, S> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) { - state().mustBe(argFilter, callObj, message, messageArgs); - return state().factory.newHeadPhaseBuilder(this); + public static <T> MapToValue<T, RMissing> missingConstant() { + return new MapToValue<>(RMissing.instance); } - default <S> HeadPhaseBuilder<S> mustBe(ArgumentFilter<? super T, S> argFilter, RError.Message message, Object... messageArgs) { - state().mustBe(argFilter, null, message, messageArgs); - return state().factory.newHeadPhaseBuilder(this); + public static <T> MapToValue<T, String> constant(String s) { + return new MapToValue<>(s); } - default <S> HeadPhaseBuilder<S> mustBe(ArgumentFilter<? super T, S> argFilter) { - return mustBe(argFilter, state().defaultError().message, state().defaultError().args); + public static <T> MapToValue<T, Integer> constant(int i) { + return new MapToValue<>(i); } - default <S> HeadPhaseBuilder<S> mustBe(Class<S> cls, RError.Message message, Object... messageArgs) { - mustBe(Predef.instanceOf(cls), message, messageArgs); - return state().factory.newHeadPhaseBuilder(this); + public static <T> MapToValue<T, Double> constant(double d) { + return new MapToValue<>(d); } - default <S> HeadPhaseBuilder<S> mustBe(Class<S> cls) { - mustBe(Predef.instanceOf(cls)); - return state().factory.newHeadPhaseBuilder(this); + public static <T> MapToValue<T, Byte> constant(byte l) { + return new MapToValue<>(l); } - default <S> HeadPhaseBuilder<S> shouldBe(Class<S> cls, RBaseNode callObj, RError.Message message, Object... messageArgs) { - shouldBe(Predef.instanceOf(cls), callObj, message, messageArgs); - return state().factory.newHeadPhaseBuilder(this); + public static <T> MapToValue<T, RIntVector> emptyIntegerVector() { + return new MapToValue<>(RDataFactory.createEmptyIntVector()); } - default <S> HeadPhaseBuilder<S> shouldBe(Class<S> cls, RError.Message message, Object... messageArgs) { - shouldBe(Predef.instanceOf(cls), message, messageArgs); - return state().factory.newHeadPhaseBuilder(this); + public static <T> MapToValue<T, RDoubleVector> emptyDoubleVector() { + return new MapToValue<>(RDataFactory.createEmptyDoubleVector()); } - default <S> HeadPhaseBuilder<S> shouldBe(Class<S> cls) { - shouldBe(Predef.instanceOf(cls)); - return state().factory.newHeadPhaseBuilder(this); + public static <T> MapToValue<T, RLogicalVector> emptyLogicalVector() { + return new MapToValue<>(RDataFactory.createEmptyLogicalVector()); } - default HeadPhaseBuilder<T> notNA(RBaseNode callObj, RError.Message message, Object... messageArgs) { - state().castBuilder().insert(state().index(), NonNANodeGen.create(callObj, message, messageArgs, null)); - return this; + public static <T> MapToValue<T, RComplexVector> emptyComplexVector() { + return new MapToValue<>(RDataFactory.createEmptyComplexVector()); } - default HeadPhaseBuilder<T> notNA(RError.Message message, Object... messageArgs) { - state().castBuilder().insert(state().index(), NonNANodeGen.create(null, message, messageArgs, null)); - return this; + public static <T> MapToValue<T, RStringVector> emptyStringVector() { + return new MapToValue<>(RDataFactory.createEmptyStringVector()); } - default HeadPhaseBuilder<T> notNA(T naReplacement, RBaseNode callObj, RError.Message message, Object... messageArgs) { - state().castBuilder().insert(state().index(), NonNANodeGen.create(callObj, message, messageArgs, naReplacement)); - return this; + public static <T> MapToValue<T, RList> emptyList() { + return new MapToValue<>(RDataFactory.createList()); } - - default HeadPhaseBuilder<T> notNA(T naReplacement, RError.Message message, Object... messageArgs) { - state().castBuilder().insert(state().index(), NonNANodeGen.create(null, message, messageArgs, naReplacement)); - return this; - } - - default HeadPhaseBuilder<T> notNA() { - state().castBuilder().insert(state().index(), NonNANodeGen.create(state().defaultError().callObj, state().defaultError().message, state().defaultError().args, null)); - return this; - } - - default HeadPhaseBuilder<T> notNA(T naReplacement) { - state().castBuilder().insert(state().index(), NonNANodeGen.create(naReplacement)); - return this; - } - } - - final class ArgCastBuilderFactoryImpl implements ArgCastBuilderFactory { - - private final int argumentIndex; - private final String argumentName; - - ArgCastBuilderFactoryImpl(int argumentIndex, String argumentName) { - this.argumentIndex = argumentIndex; - this.argumentName = argumentName; - } - - @Override - public InitialPhaseBuilderImpl<Object> newInitialPhaseBuilder() { - return new InitialPhaseBuilderImpl<>(); - } - - @Override - public <T> InitialPhaseBuilderImpl<T> newInitialPhaseBuilder(ArgCastBuilder<?, ?> currentBuilder) { - return new InitialPhaseBuilderImpl<>(currentBuilder.state()); - } - - @Override - public <T extends RAbstractVector, S> CoercedPhaseBuilderImpl<T, S> newCoercedPhaseBuilder(ArgCastBuilder<?, ?> currentBuilder, Class<?> elementClass) { - return new CoercedPhaseBuilderImpl<>(currentBuilder.state(), elementClass); - } - - @Override - public <T> HeadPhaseBuilderImpl<T> newHeadPhaseBuilder(ArgCastBuilder<?, ?> currentBuilder) { - return new HeadPhaseBuilderImpl<>(currentBuilder.state()); - } - - public final class InitialPhaseBuilderImpl<T> extends ArgCastBuilderBase<T, InitialPhaseBuilder<T>> implements InitialPhaseBuilder<T> { - InitialPhaseBuilderImpl(ArgCastBuilderState state) { - super(new ArgCastBuilderState(state, false)); - } - - InitialPhaseBuilderImpl() { - super(new ArgCastBuilderState(argumentIndex, argumentName, ArgCastBuilderFactoryImpl.this, CastBuilder.this, false)); - } - } - - public final class CoercedPhaseBuilderImpl<T extends RAbstractVector, S> extends ArgCastBuilderBase<T, CoercedPhaseBuilder<T, S>> implements CoercedPhaseBuilder<T, S> { - - private final Class<?> elementClass; - - CoercedPhaseBuilderImpl(ArgCastBuilderState state, Class<?> elementClass) { - super(new ArgCastBuilderState(state, true)); - this.elementClass = elementClass; - } - - @Override - public Class<?> elementClass() { - return elementClass; - } - } - - public final class HeadPhaseBuilderImpl<T> extends ArgCastBuilderBase<T, HeadPhaseBuilder<T>> implements HeadPhaseBuilder<T> { - HeadPhaseBuilderImpl(ArgCastBuilderState state) { - super(new ArgCastBuilderState(state, false)); - } - } - - } - - public static final class ChainBuilder<T> { - private final Function<ArgCastBuilder<T, ?>, CastNode> firstCastNodeFactory; - - private ChainBuilder(Function<ArgCastBuilder<T, ?>, CastNode> firstCastNodeFactory) { - this.firstCastNodeFactory = firstCastNodeFactory; - } - - private Function<ArgCastBuilder<T, ?>, CastNode> makeChain(Function<ArgCastBuilder<T, ?>, CastNode> secondCastNodeFactory) { - return phaseBuilder -> { - CastNode firstCast = firstCastNodeFactory.apply(phaseBuilder); - CastNode secondCast = secondCastNodeFactory.apply(phaseBuilder); - return new ChainedCastNode(firstCast, secondCast); - }; - } - - @SuppressWarnings("overloads") - public ChainBuilder<T> with(Function<ArgCastBuilder<T, ?>, CastNode> secondCastNodeFactory) { - return new ChainBuilder<>(makeChain(secondCastNodeFactory)); - } - - @SuppressWarnings("overloads") - public ChainBuilder<T> with(ArgumentMapper<?, ?> mapper) { - return with(Predef.map(mapper)); - } - - public ChainBuilder<T> with(CastNode secondCastNode) { - return new ChainBuilder<>(makeChain(pb -> secondCastNode)); - } - - public Function<ArgCastBuilder<T, ?>, CastNode> end() { - return firstCastNodeFactory; - } - - } - - public static final class FindFirstNodeBuilder<T> { - private final RBaseNode callObj; - private final Message message; - private final Object[] messageArgs; - - private FindFirstNodeBuilder(RBaseNode callObj, Message message, Object[] messageArgs) { - this.callObj = callObj; - this.message = message; - this.messageArgs = messageArgs; - } - - private Function<ArgCastBuilder<T, ?>, CastNode> create(Class<?> elementClass, Object defaultValue) { - return phaseBuilder -> { - Message actualMessage = message; - Object[] actualMessageArgs = messageArgs; - RBaseNode actualCallObj = callObj; - if (message == null) { - DefaultError err = phaseBuilder.state().isDefaultErrorDefined() ? phaseBuilder.state().defaultError() : new DefaultError(null, RError.Message.LENGTH_ZERO); - actualMessage = err.message; - actualMessageArgs = err.args; - actualCallObj = err.callObj; - } - return FindFirstNodeGen.create(elementClass, actualCallObj, actualMessage, actualMessageArgs, defaultValue); - }; - } - - public Function<ArgCastBuilder<T, ?>, CastNode> logicalElement() { - return create(Byte.class, null); - } - - public Function<ArgCastBuilder<T, ?>, CastNode> logicalElement(byte defaultValue) { - return create(Byte.class, defaultValue); - } - - public Function<ArgCastBuilder<T, ?>, CastNode> doubleElement() { - return create(Double.class, null); - } - - public Function<ArgCastBuilder<T, ?>, CastNode> doubleElement(double defaultValue) { - return create(Double.class, defaultValue); - } - - public Function<ArgCastBuilder<T, ?>, CastNode> integerElement() { - return create(Integer.class, null); - } - - public Function<ArgCastBuilder<T, ?>, CastNode> integerElement(int defaultValue) { - return create(Integer.class, defaultValue); - } - - public Function<ArgCastBuilder<T, ?>, CastNode> stringElement() { - return create(String.class, null); - } - - public Function<ArgCastBuilder<T, ?>, CastNode> stringElement(String defaultValue) { - return create(String.class, defaultValue); - } - - public Function<ArgCastBuilder<T, ?>, CastNode> objectElement() { - return create(Object.class, null); - } - - public Function<ArgCastBuilder<T, ?>, CastNode> objectElement(Object defaultValue) { - return create(Object.class, defaultValue); - } - - } - } 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 2b0cce3072a90103586c8a2311cb0742f426d116..681d84371ec7f0f4b67c57d2eac6d25a529b9c92 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 @@ -31,6 +31,7 @@ import com.oracle.truffle.r.runtime.RVisibility; import com.oracle.truffle.r.runtime.builtins.RBehavior; import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; +import com.oracle.truffle.r.runtime.builtins.RSpecialFactory; import com.oracle.truffle.r.runtime.nodes.RNode; public final class RBuiltinFactory extends RBuiltinDescriptor { @@ -38,8 +39,8 @@ public final class RBuiltinFactory extends RBuiltinDescriptor { private final Function<RNode[], RBuiltinNode> constructor; RBuiltinFactory(String name, Class<?> builtinNodeClass, RVisibility visibility, String[] aliases, RBuiltinKind kind, ArgumentsSignature signature, int[] nonEvalArgs, boolean splitCaller, - boolean alwaysSplit, RDispatch dispatch, Function<RNode[], RBuiltinNode> constructor, RBehavior behavior) { - super(name, builtinNodeClass, visibility, aliases, kind, signature, nonEvalArgs, splitCaller, alwaysSplit, dispatch, behavior); + boolean alwaysSplit, RDispatch dispatch, Function<RNode[], RBuiltinNode> constructor, RBehavior behavior, RSpecialFactory specialCall) { + super(name, builtinNodeClass, visibility, aliases, kind, signature, nonEvalArgs, splitCaller, alwaysSplit, dispatch, behavior, specialCall); this.constructor = constructor; } 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 86bf53a2747bd84ebfc7167d7c2e9dcec3c9be66..1e9a808b1fc69fb21424eaf07615291ad937f0c8 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 @@ -51,14 +51,14 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @NodeChild(value = "arguments", type = RNode[].class) public abstract class RBuiltinNode extends RNode { - public abstract Object execute(VirtualFrame frame, Object... args); + public abstract Object executeBuiltin(VirtualFrame frame, Object... args); protected void createCasts(@SuppressWarnings("unused") CastBuilder casts) { // nothing to do } public CastNode[] getCasts() { - CastBuilder builder = new CastBuilder(this); + CastBuilder builder = new CastBuilder(getRBuiltin()); createCasts(builder); return builder.getCasts(); } 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 12b61f2bc13a85ee86ec411a2b0316c59d33656b..f402cf9e9b67a70256cf38da66b21263de5f693d 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 @@ -29,17 +29,19 @@ import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.r.nodes.RRootNode; import com.oracle.truffle.r.nodes.function.FormalArguments; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.RDispatch; import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.FastPathFactory; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; public final class RBuiltinRootNode extends RRootNode { @Child private RBuiltinNode builtin; + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); + private final RBuiltinFactory factory; RBuiltinRootNode(RBuiltinFactory factory, RBuiltinNode builtin, FormalArguments formalArguments, FrameDescriptor frameDescriptor, FastPathFactory fastPath) { @@ -63,20 +65,19 @@ public final class RBuiltinRootNode extends RRootNode { @Override public Object execute(VirtualFrame frame) { verifyEnclosingAssumptions(frame); - Object result = null; try { if (builtin == null) { assert factory.getDispatch() == RDispatch.SPECIAL : "null builtin node only allowed for SPECIAL dispatch"; throw RError.error(RError.SHOW_CALLER, Message.INVALID_USE, factory.getName()); } - result = builtin.execute(frame); + return builtin.execute(frame); } catch (NullPointerException | ArrayIndexOutOfBoundsException | AssertionError e) { CompilerDirectives.transferToInterpreter(); throw new RInternalError(e, "internal error"); + } finally { + visibility.execute(frame, factory.getVisibility()); + visibility.executeEndOfFunction(frame); } - - RContext.getInstance().setVisible(factory.getVisibility()); - return result; } public RBuiltinNode getBuiltinNode() { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInternalCodeBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInternalCodeBuiltinNode.java index cf4cdca50cb5a10f779dbdcbcef25a57ed40dda5..6099c04dfecf655d59ff6d3a77b9e66864e4ba08 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInternalCodeBuiltinNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInternalCodeBuiltinNode.java @@ -33,6 +33,11 @@ import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RFunction; +/** + * Node that can route external calls like .External to an R function. The reference count of the + * arguments does not get incremented for this call, like for other built-in calls, however, this + * means that the R code should not update its arguments unless it makes a copy! + */ public final class RInternalCodeBuiltinNode extends RExternalBuiltinNode { private final RContext context; @@ -61,9 +66,11 @@ public final class RInternalCodeBuiltinNode extends RExternalBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); RInternalCode internalCode = RInternalCode.lookup(context, basePackage, code); this.function = internalCode.lookupFunction(functionName); + if (this.function == null) { + throw RInternalError.shouldNotReachHere("Could not load RInternalCodeBuiltin function '" + functionName + "'."); + } } return call.execute(frame, actualArgs.getSignature(), actualArgs.getArguments(), function, functionName, null); } - } 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 94eab484b0f8a1e8ad3c4def1024f0402fe05875..385e36f70eba6ff3c170d8cb12447f3372604430 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 @@ -24,8 +24,9 @@ package com.oracle.truffle.r.nodes.builtin; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RStringVector; +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; @@ -34,12 +35,14 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; */ public final class RList2EnvNode extends RBaseNode { + private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + @TruffleBoundary - public REnvironment execute(RList list, REnvironment env) { + public REnvironment execute(RAbstractListVector list, REnvironment env) { if (list.getLength() == 0) { return env; } - RStringVector names = list.getNames(); + RStringVector names = list.getNames(attrProfiles); if (names == null) { throw RError.error(this, RError.Message.LIST_NAMES_SAME_LENGTH); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/TypePredicateArgumentFilter.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/TypePredicateArgumentFilter.java index 27b7a04ba5a117b1855f3556bff9e8b418494977..7039100cfeba7597f792fc97087049e1a3db5d42 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/TypePredicateArgumentFilter.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/TypePredicateArgumentFilter.java @@ -28,12 +28,12 @@ import com.oracle.truffle.r.nodes.builtin.ArgumentFilter.ArgumentTypeFilter; public class TypePredicateArgumentFilter<T, R extends T> extends AbstractPredicateArgumentFilter<T, R> implements ArgumentTypeFilter<T, R> { - public TypePredicateArgumentFilter(Predicate<? super T> valuePredicate, boolean isNullable) { - super(valuePredicate, isNullable); + public TypePredicateArgumentFilter(Predicate<? super T> valuePredicate) { + super(valuePredicate); } public static <T, R extends T> TypePredicateArgumentFilter<T, R> fromLambda(Predicate<? super T> predicate) { - return new TypePredicateArgumentFilter<>(predicate, false); + return new TypePredicateArgumentFilter<>(predicate); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/ValuePredicateArgumentFilter.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/ValuePredicateArgumentFilter.java index 3da12e4940d7178e6e5d6b08154a53e2236aa7f7..d59ba742832614c52875e1de16af88e3c5a4833b 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/ValuePredicateArgumentFilter.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/ValuePredicateArgumentFilter.java @@ -28,12 +28,12 @@ import com.oracle.truffle.r.nodes.builtin.ArgumentFilter.ArgumentValueFilter; public class ValuePredicateArgumentFilter<T> extends AbstractPredicateArgumentFilter<T, T> implements ArgumentValueFilter<T> { - public ValuePredicateArgumentFilter(Predicate<? super T> valuePredicate, boolean isNullable) { - super(valuePredicate, isNullable); + public ValuePredicateArgumentFilter(Predicate<? super T> valuePredicate) { + super(valuePredicate); } public static <T> ValuePredicateArgumentFilter<T> fromLambda(Predicate<? super T> predicate) { - return new ValuePredicateArgumentFilter<>(predicate, false); + return new ValuePredicateArgumentFilter<>(predicate); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/VectorPredicateArgumentFilter.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/VectorPredicateArgumentFilter.java index 4ddddde971ab2665c2345d666e19a867d79b424a..23ee19681bf47a7eb830275c0e433eaef763651c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/VectorPredicateArgumentFilter.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/VectorPredicateArgumentFilter.java @@ -28,8 +28,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; public class VectorPredicateArgumentFilter<T extends RAbstractVector> extends ValuePredicateArgumentFilter<T> { - public VectorPredicateArgumentFilter(Predicate<T> valuePredicate, boolean isNullable) { - super(valuePredicate, isNullable); + public VectorPredicateArgumentFilter(Predicate<T> valuePredicate) { + super(valuePredicate); } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..94badcc9ef9aa51e4b3350e89ee6363823f6ba74 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java @@ -0,0 +1,444 @@ +/* + * 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.builtin.casts; + +import com.oracle.truffle.r.nodes.builtin.ArgumentFilter; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep; +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +/** + * Represents filters that can be used in {@link FilterStep} and as condition in {@link MapStep}. + */ +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 abstract <D> D accept(FilterVisitor<D> visitor); + + public <S extends R> AndFilter<T, S> and(Filter<? super R, S> other) { + return new AndFilter<>(this, other); + } + + public OrFilter<T> or(Filter<T, ? extends T> other) { + return new OrFilter<>(this, other); + } + + public NotFilter<T> not() { + return new NotFilter<>(this); + } + + public interface FilterVisitor<D> { + D visit(TypeFilter<?, ?> filter); + + D visit(RTypeFilter<?> filter); + + D visit(CompareFilter<?> filter); + + D visit(AndFilter<?, ?> filter); + + D visit(OrFilter<?> filter); + + D visit(NotFilter<?> filter); + + D visit(MatrixFilter<?> filter); + + D visit(DoubleFilter filter); + } + + /** + * Filters specific Java class. + */ + public static final class TypeFilter<T, R extends T> extends Filter<T, R> { + private final Class<?>[] type; + private final ArgumentFilter<Object, Object> instanceOfLambda; + + public TypeFilter(ArgumentFilter<Object, Object> instanceOfLambda, Class<?>... type) { + this.type = type; + this.instanceOfLambda = instanceOfLambda; + } + + public Class<?>[] getType() { + return type; + } + + @Override + public boolean isNarrowing() { + return true; + } + + public ArgumentFilter<Object, Object> getInstanceOfLambda() { + return instanceOfLambda; + } + + @Override + public <D> D accept(FilterVisitor<D> visitor) { + return visitor.visit(this); + } + } + + /** + * Filters specified set of type in R sense, supports only vector types minus list. + */ + public static final class RTypeFilter<T extends RAbstractVector> extends Filter<Object, T> { + private final RType type; + + public RTypeFilter(RType type) { + assert type.isVector() && type != RType.List : "RTypeFilter supports only vector types minus list."; + this.type = type; + } + + public RType getType() { + return type; + } + + @Override + public boolean isNarrowing() { + return true; + } + + @Override + public <D> D accept(FilterVisitor<D> visitor) { + return visitor.visit(this); + } + } + + /** + * Compares the real value against given value using given operation. Use the constants defined + * within this class for the operation. + */ + public static final class CompareFilter<T> extends Filter<T, T> { + + public interface Subject { + <D> D accept(SubjectVisitor<D> visitor, byte operation); + } + + public interface SubjectVisitor<D> { + D visit(ScalarValue scalarValue, byte operation); + + D visit(NATest naTest, byte operation); + + D visit(StringLength stringLength, byte operation); + + D visit(VectorSize vectorSize, byte operation); + + D visit(ElementAt elementAt, byte operation); + + D visit(Dim dim, byte operation); + } + + public static final class ScalarValue implements Subject { + public final Object value; + public final RType type; + + public ScalarValue(Object value, RType type) { + this.value = value; + this.type = type; + } + + @Override + public <D> D accept(SubjectVisitor<D> visitor, byte operation) { + return visitor.visit(this, operation); + } + + } + + public static final class NATest implements Subject { + public final RType type; + + public NATest(RType type) { + this.type = type; + } + + @Override + public <D> D accept(SubjectVisitor<D> visitor, byte operation) { + return visitor.visit(this, operation); + } + + } + + public static final class StringLength implements Subject { + public final int length; + + public StringLength(int length) { + this.length = length; + } + + @Override + public <D> D accept(SubjectVisitor<D> visitor, byte operation) { + return visitor.visit(this, operation); + } + } + + public static final class VectorSize implements Subject { + public final int size; + + public VectorSize(int size) { + this.size = size; + } + + @Override + public <D> D accept(SubjectVisitor<D> visitor, byte operation) { + return visitor.visit(this, operation); + } + } + + public static final class ElementAt implements Subject { + public final int index; + public final Object value; + public final RType type; + + public ElementAt(int index, Object value, RType type) { + this.index = index; + this.value = value; + this.type = type; + } + + @Override + public <D> D accept(SubjectVisitor<D> visitor, byte operation) { + return visitor.visit(this, operation); + } + } + + public static final class Dim implements Subject { + public final int dimIndex; + public final int dimSize; + + public Dim(int dimIndex, int dimSize) { + this.dimIndex = dimIndex; + this.dimSize = dimSize; + } + + @Override + public <D> D accept(SubjectVisitor<D> visitor, byte operation) { + return visitor.visit(this, operation); + } + } + + public static final byte EQ = 0; + public static final byte GT = 1; + public static final byte LT = 2; + public static final byte GE = 3; + public static final byte LE = 4; + public static final byte SAME = 5; + + private final byte operation; + private final Subject subject; + + public CompareFilter(byte operation, Subject subject) { + assert operation <= SAME : "wrong operation value"; + this.operation = operation; + this.subject = subject; + } + + @Override + public boolean isNarrowing() { + return false; + } + + public Subject getSubject() { + return subject; + } + + public byte getOperation() { + return operation; + } + + @Override + public <D> D accept(FilterVisitor<D> visitor) { + return visitor.visit(this); + } + } + + public abstract static class MatrixFilter<T extends RAbstractVector> extends Filter<T, T> { + + private static final MatrixFilter<RAbstractVector> IS_MATRIX = new MatrixFilter<RAbstractVector>() { + @Override + public <D> D acceptOperation(OperationVisitor<D> visitor) { + return visitor.visitIsMatrix(); + } + }; + + private static final MatrixFilter<RAbstractVector> IS_SQUARE_MATRIX = new MatrixFilter<RAbstractVector>() { + @Override + public <D> D acceptOperation(OperationVisitor<D> visitor) { + return visitor.visitIsSquareMatrix(); + } + }; + + public interface OperationVisitor<D> { + D visitIsMatrix(); + + D visitIsSquareMatrix(); + } + + @SuppressWarnings("unchecked") + public static <T extends RAbstractVector> MatrixFilter<T> isMatrixFilter() { + return (MatrixFilter<T>) IS_MATRIX; + } + + @SuppressWarnings("unchecked") + public static <T extends RAbstractVector> MatrixFilter<T> isSquareMatrixFilter() { + return (MatrixFilter<T>) IS_SQUARE_MATRIX; + } + + private MatrixFilter() { + } + + @Override + public boolean isNarrowing() { + return false; + } + + public abstract <D> D acceptOperation(OperationVisitor<D> visitor); + + @Override + public <D> D accept(FilterVisitor<D> visitor) { + return visitor.visit(this); + } + } + + public abstract static class DoubleFilter extends Filter<Double, Double> { + + public static final DoubleFilter IS_FINITE = new DoubleFilter() { + @Override + public <D> D acceptOperation(OperationVisitor<D> visitor) { + return visitor.visitIsFinite(); + } + }; + + public static final DoubleFilter IS_FRACTIONAL = new DoubleFilter() { + @Override + public <D> D acceptOperation(OperationVisitor<D> visitor) { + return visitor.visitIsFractional(); + } + }; + + public interface OperationVisitor<D> { + D visitIsFinite(); + + D visitIsFractional(); + } + + private DoubleFilter() { + + } + + @Override + public boolean isNarrowing() { + return false; + } + + public abstract <D> D acceptOperation(OperationVisitor<D> visitor); + + @Override + public <D> D accept(FilterVisitor<D> visitor) { + return visitor.visit(this); + } + } + + public static final class AndFilter<T, R extends T> extends Filter<T, R> { + private final Filter<?, ?> left; + private final Filter<?, ?> right; + + public AndFilter(Filter<?, ?> left, Filter<?, ?> right) { + this.left = left; + this.right = right; + } + + @Override + public boolean isNarrowing() { + return left.isNarrowing() || right.isNarrowing(); + } + + public Filter<?, ?> getLeft() { + return left; + } + + public Filter<?, ?> getRight() { + return right; + } + + @Override + public <D> D accept(FilterVisitor<D> visitor) { + return visitor.visit(this); + } + } + + public static final class OrFilter<T> extends Filter<T, T> { + private final Filter<?, ?> left; + private final Filter<?, ?> right; + + public OrFilter(Filter<?, ?> left, Filter<?, ?> right) { + this.left = left; + this.right = right; + } + + @Override + public boolean isNarrowing() { + return false; + } + + public Filter<?, ?> getLeft() { + return left; + } + + public Filter<?, ?> getRight() { + return right; + } + + @Override + public <D> D accept(FilterVisitor<D> visitor) { + return visitor.visit(this); + } + } + + public static final class NotFilter<T> extends Filter<T, T> { + private final Filter<?, ?> filter; + + public NotFilter(Filter<?, ?> filter) { + 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); + } + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..c47c8dd1797ff1299d932daaba0015aa57657184 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Mapper.java @@ -0,0 +1,110 @@ +/* + * 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.builtin.casts; + +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep; + +/** + * Represents mapping used in {@link MapStep}. + */ +public abstract class Mapper<T, R> { + + public abstract <D> D accept(MapperVisitor<D> visitor); + + public interface MapperVisitor<D> { + D visit(MapToValue<?, ?> mapper); + + D visit(MapByteToBoolean mapper); + + D visit(MapDoubleToInt mapper); + + D visit(MapToCharAt mapper); + } + + public static final class MapToValue<T, R> extends Mapper<T, R> { + private final Object value; + + public MapToValue(Object value) { + this.value = value; + } + + public Object getValue() { + return value; + } + + @Override + public <D> D accept(MapperVisitor<D> visitor) { + return visitor.visit(this); + } + } + + public static final class MapByteToBoolean extends Mapper<Byte, Boolean> { + + public static final MapByteToBoolean INSTANCE = new MapByteToBoolean(); + + private MapByteToBoolean() { + + } + + @Override + public <D> D accept(MapperVisitor<D> visitor) { + return visitor.visit(this); + } + } + + public static final class MapDoubleToInt extends Mapper<Double, Integer> { + + public static final MapDoubleToInt INSTANCE = new MapDoubleToInt(); + + private MapDoubleToInt() { + } + + @Override + public <D> D accept(MapperVisitor<D> visitor) { + return visitor.visit(this); + } + } + + public static final class MapToCharAt extends Mapper<String, Integer> { + private final int index; + private final int defaultValue; + + public MapToCharAt(int index, int defaultValue) { + this.index = index; + this.defaultValue = defaultValue; + } + + public int getIndex() { + return index; + } + + public int getDefaultValue() { + return defaultValue; + } + + @Override + public <D> D accept(MapperVisitor<D> visitor) { + return visitor.visit(this); + } + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..d82b22e6c46a4d0faf36a3a5bd674f8fe144f4a5 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java @@ -0,0 +1,72 @@ +/* + * 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.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; + +/** + * 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; + this.message = message; + this.messageArgs = messageArgs; + } + + public RBaseNode getCallObj() { + return callObj; + } + + public Message getMessage() { + return message; + } + + public Object[] getMessageArgs() { + 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; + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..3ecb60adfca4cf4eb01255ed452e965b90bec7d4 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java @@ -0,0 +1,111 @@ +/* + * 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.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}. + * If there is no RNull/RMissing mapper, then RNull/RMissing should cause error, if there is + * RNull/RMissing mapper and the RNull/RMissing message is set, then this message will be used as + * 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; + + public PipelineConfig(String argumentName, MessageData defaultError, MessageData defaultWarning, Mapper<? super RMissing, ?> missingMapper, Mapper<? super RNull, ?> nullMapper, + MessageData missingMsg, + MessageData nullMsg) { + this.defaultError = defaultError; + this.defaultWarning = defaultWarning; + this.missingMapper = missingMapper; + this.nullMapper = nullMapper; + this.missingMsg = missingMsg; + this.nullMsg = nullMsg; + this.argumentName = argumentName; + } + + /** + * Default message that should be used when no explicit default error/warning was set. For the + * time being this is not configurable. + */ + public MessageData getDefaultDefaultMessage() { + return new MessageData(null, RError.Message.INVALID_ARGUMENT, argumentName); + } + + public MessageData getDefaultError() { + return defaultError; + } + + public MessageData getDefaultWarning() { + 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 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 new file mode 100644 index 0000000000000000000000000000000000000000..a13c29fc1cad2114fe791f136ffc9d55f9f91550 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java @@ -0,0 +1,337 @@ +/* + * 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.builtin.casts; + +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +/** + * Represents a single step in the cast pipeline. {@code PipelineStep}, {@code Mapper} and + * {@code Filter} are only symbolic representation of the pipeline, these objects can be transformed + * to something useful by using corresponding visitors, e.g. {@linek PipelineStepVisitor}. Steps can + * be chained as a linked list by setting the next step in the chain using + * {@link #setNext(PipelineStep)}. The order of steps should be the same as the order of cast + * pipeline API invocations. + */ +public abstract class PipelineStep<T, R> { + + private PipelineStep<?, ?> next; + + public final PipelineStep<?, ?> getNext() { + return next; + } + + public final PipelineStep<?, ?> setNext(PipelineStep<?, ?> next) { + this.next = next; + return this; + } + + public abstract <D> D accept(PipelineStepVisitor<D> visitor); + + public interface PipelineStepVisitor<T> { + T visit(FindFirstStep<?, ?> step); + + T visit(CoercionStep<?, ?> step); + + T visit(MapStep<?, ?> step); + + T visit(MapIfStep<?, ?> step); + + T visit(FilterStep<?, ?> step); + + T visit(NotNAStep<?> step); + + T visit(DefaultErrorStep<?> step); + + 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); + } + } + + /** + * Boxes all primitive types (integer, string, double, byte) to {@link RAbstractVector}. + */ + public static final class BoxPrimitiveStep<T> extends PipelineStep<T, T> { + @Override + public <D> D accept(PipelineStepVisitor<D> visitor) { + return visitor.visit(this); + } + } + + /** + * If the replacement is set (!= null), then maps NA values to the replacement, otherwise raises + * given error on NA value of any type. If both the replacement and the message are set, then + * the replacement is accompanied by a warning. + */ + public static final class NotNAStep<T> extends PipelineStep<T, T> { + private final MessageData message; + private final Object replacement; + + public NotNAStep(Object replacement, MessageData message) { + this.replacement = replacement; + this.message = message; + } + + public MessageData getMessage() { + return message; + } + + public Object getReplacement() { + return replacement; + } + + @Override + public <D> D accept(PipelineStepVisitor<D> visitor) { + return visitor.visit(this); + } + } + + /** + * Takes the first element of a vector. If the default value and message are provided, then if + * 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. + */ + public static final class FindFirstStep<V, E> extends PipelineStep<V, E> { + private final MessageData error; + private final Object defaultValue; + private final Class<?> elementClass; + + public FindFirstStep(Object defaultValue, Class<?> elementClass, MessageData error) { + this.defaultValue = defaultValue; + this.elementClass = elementClass; + this.error = error; + } + + public Object getDefaultValue() { + return defaultValue; + } + + public Class<?> getElementClass() { + return elementClass; + } + + public MessageData getError() { + return error; + } + + @Override + public <D> D accept(PipelineStepVisitor<D> visitor) { + return visitor.visit(this); + } + } + + /** + * Converts the value to a vector of given type (or a vector if Any, or Attributable). Null and + * missing values are forwarded. + */ + public static final class CoercionStep<T, V> extends PipelineStep<T, V> { + public final RType type; + public final boolean preserveNames; + public final boolean preserveDimensions; + public final boolean preserveAttributes; + + /** + * Whether RNull/RMissing should be preserved, or converted to an empty list. + */ + public final boolean preserveNonVector; + + /** + * Coercion to scalar or vector type. + */ + public final boolean vectorCoercion; + + public CoercionStep(RType type, boolean vectorCoercion) { + 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); + } + + 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; + } + + public RType getType() { + return type; + } + + @Override + public <D> D accept(PipelineStepVisitor<D> visitor) { + return visitor.visit(this); + } + } + + /** + * Converts the value to a {@link com.oracle.truffle.r.runtime.data.RAttributable} instance. + */ + public static final class AttributableCoercionStep<T> extends PipelineStep<T, RAttributable> { + public final boolean preserveNames; + public final boolean preserveDimensions; + public final boolean preserveAttributes; + + public AttributableCoercionStep(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { + this.preserveNames = preserveNames; + this.preserveDimensions = preserveDimensions; + this.preserveAttributes = preserveAttributes; + } + + @Override + public <D> D accept(PipelineStepVisitor<D> visitor) { + return visitor.visit(this); + } + } + + public static final class MapStep<T, R> extends PipelineStep<T, R> { + private final Mapper<?, ?> mapper; + + public MapStep(Mapper<?, ?> mapper) { + this.mapper = mapper; + } + + public Mapper<?, ?> getMapper() { + return mapper; + } + + @Override + public <D> D accept(PipelineStepVisitor<D> visitor) { + return visitor.visit(this); + } + } + + /** + * Allows to execute on of given pipeline chains depending on the condition. + */ + public static final class MapIfStep<T, R> extends PipelineStep<T, R> { + private final Filter<?, ?> filter; + private final PipelineStep<?, ?> trueBranch; + private final PipelineStep<?, ?> falseBranch; + + public MapIfStep(Filter<?, ?> filter, PipelineStep<?, ?> trueBranch, PipelineStep<?, ?> falseBranch) { + this.filter = filter; + this.trueBranch = trueBranch; + this.falseBranch = falseBranch; + } + + public Filter<?, ?> getFilter() { + return filter; + } + + public PipelineStep<?, ?> getTrueBranch() { + return trueBranch; + } + + public PipelineStep<?, ?> getFalseBranch() { + return falseBranch; + } + + @Override + public <D> D accept(PipelineStepVisitor<D> visitor) { + return visitor.visit(this); + } + } + + /** + * Raises an error if the value does not conform to the given filter. + */ + public static final class FilterStep<T, R extends T> extends PipelineStep<T, R> { + private final Filter<?, ?> filter; + private final MessageData message; + private final boolean isWarning; + + public FilterStep(Filter<?, ?> filter, MessageData message, boolean isWarning) { + this.filter = filter; + this.message = message; + this.isWarning = isWarning; + } + + public Filter<?, ?> getFilter() { + return filter; + } + + public MessageData getMessage() { + return message; + } + + public boolean isWarning() { + return isWarning; + } + + @Override + public <D> D accept(PipelineStepVisitor<D> visitor) { + return visitor.visit(this); + } + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..62a36d3fe0dbd00861a40a3e90e59a382b70cbcd --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java @@ -0,0 +1,798 @@ +/* + * 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.builtin.casts; + +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; +import com.oracle.truffle.r.nodes.builtin.ArgumentMapper; +import com.oracle.truffle.r.nodes.builtin.ValuePredicateArgumentMapper; +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.NotFilter; +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.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; +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.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; +import com.oracle.truffle.r.nodes.unary.CastIntegerBaseNodeGen; +import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; +import com.oracle.truffle.r.nodes.unary.CastLogicalBaseNodeGen; +import com.oracle.truffle.r.nodes.unary.CastLogicalNodeGen; +import com.oracle.truffle.r.nodes.unary.CastNode; +import com.oracle.truffle.r.nodes.unary.CastRawNodeGen; +import com.oracle.truffle.r.nodes.unary.CastStringBaseNodeGen; +import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; +import com.oracle.truffle.r.nodes.unary.CastToAttributableNodeGen; +import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen; +import com.oracle.truffle.r.nodes.unary.ChainedCastNode; +import com.oracle.truffle.r.nodes.unary.ConditionalMapNode; +import com.oracle.truffle.r.nodes.unary.FilterNode; +import com.oracle.truffle.r.nodes.unary.FindFirstNodeGen; +import com.oracle.truffle.r.nodes.unary.MapNode; +import com.oracle.truffle.r.nodes.unary.NonNANodeGen; +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.Utils; +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; +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.ops.na.NACheck; + +/** + * Converts given pipeline into corresponding cast nodes chain. + */ +public final class PipelineToCastNode { + + private PipelineToCastNode() { + // nop: static class + } + + public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStep) { + return convert(config, firstStep, PipelineConfig.getFilterFactory(), PipelineConfig.getMapperFactory()); + } + + public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStep, ArgumentFilterFactory filterFactory, ArgumentMapperFactory mapperFactory) { + if (firstStep == null) { + return BypassNode.create(config, null, mapperFactory, null); + } else { + CastNodeFactory nodeFactory = new CastNodeFactory(filterFactory, mapperFactory, config.getDefaultDefaultMessage()); + SinglePrimitiveOptimization singleOptVisitor = new SinglePrimitiveOptimization(nodeFactory); + CastNode headNode = convert(firstStep, singleOptVisitor); + return singleOptVisitor.createBypassNode(config, headNode, mapperFactory); + } + } + + /** + * Converts chain of pipeline steps to cast nodes. + */ + private static CastNode convert(PipelineStep<?, ?> firstStep, PipelineStepVisitor<CastNode> nodeFactory) { + if (firstStep == null) { + return null; + } + + CastNode prevCastNode = null; + PipelineStep<?, ?> currCastStep = firstStep; + while (currCastStep != null) { + CastNode node = currCastStep.accept(nodeFactory); + if (node != null) { + if (prevCastNode == null) { + prevCastNode = node; + } else { + CastNode finalPrevCastNode = prevCastNode; + prevCastNode = new ChainedCastNode(() -> finalPrevCastNode, () -> node); + } + } + + currCastStep = currCastStep.getNext(); + } + 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; + + /** + * 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) { + 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; + } + + @Override + public CastNode visit(DefaultWarningStep<?> step) { + defaultWarning = step.getDefaultMessage(); + return null; + } + + @Override + public CastNode visit(BoxPrimitiveStep<?> step) { + return BoxPrimitiveNode.create(); + } + + @Override + public CastNode visit(FindFirstStep<?, ?> step) { + boxPrimitives = false; + + // See FindFirstStep documentation on how it should be interpreted + if (step.getDefaultValue() == null) { + MessageData msg = step.getError(); + if (msg == null) { + // Note: intentional direct use of defaultError + msg = defaultError != null ? defaultError : new MessageData(null, RError.Message.LENGTH_ZERO); + } + return FindFirstNodeGen.create(step.getElementClass(), msg.getCallObj(), msg.getMessage(), msg.getMessageArgs(), 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()); + } + } + } + + @Override + public CastNode visit(FilterStep<?, ?> step) { + ArgumentFilter<?, ?> filter = filterFactory.createFilter(step.getFilter()); + MessageData msg = getDefaultIfNull(step.getMessage(), step.isWarning()); + return FilterNode.create(filter, step.isWarning(), msg.getCallObj(), msg.getMessage(), msg.getMessageArgs(), boxPrimitives); + } + + @Override + public CastNode visit(NotNAStep<?> step) { + if (step.getReplacement() == null) { + MessageData msg = getDefaultErrorIfNull(step.getMessage()); + return NonNANodeGen.create(msg.getCallObj(), msg.getMessage(), msg.getMessageArgs(), step.getReplacement()); + } else { + MessageData msg = step.getMessage(); + if (msg == null) { + return NonNANodeGen.create(null, null, null, step.getReplacement()); + } else { + return NonNANodeGen.create(msg.getCallObj(), msg.getMessage(), msg.getMessageArgs(), step.getReplacement()); + } + } + } + + @Override + public CastNode visit(CoercionStep<?, ?> step) { + boxPrimitives = true; + + RType type = step.getType(); + switch (type) { + case Integer: + 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) + : 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) + : CastLogicalBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); + case Complex: + return CastComplexNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); + case Raw: + return CastRawNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); + case Any: + return CastToVectorNodeGen.create(step.preserveNonVector); + default: + throw RInternalError.shouldNotReachHere(Utils.stringFormat("Unsupported type '%s' in AsVectorStep.", type)); + } + } + + @Override + public CastNode visit(AttributableCoercionStep<?> step) { + return CastToAttributableNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); + } + + @Override + public CastNode visit(MapStep<?, ?> step) { + return MapNode.create(mapperFactory.createMapper(step.getMapper())); + } + + @Override + public CastNode visit(MapIfStep<?, ?> step) { + ArgumentFilter<?, ?> condition = filterFactory.createFilter(step.getFilter()); + CastNode trueCastNode = PipelineToCastNode.convert(step.getTrueBranch(), this); + CastNode falseCastNode = PipelineToCastNode.convert(step.getFalseBranch(), this); + return ConditionalMapNode.create(condition, trueCastNode, falseCastNode); + } + + 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); + } + } + + public interface ArgumentFilterFactory { + ArgumentFilter<?, ?> createFilter(Filter<?, ?> filter); + } + + public static final class ArgumentFilterFactoryImpl + implements ArgumentFilterFactory, FilterVisitor<ArgumentFilter<?, ?>>, MatrixFilter.OperationVisitor<ArgumentFilter<RAbstractVector, RAbstractVector>>, + DoubleFilter.OperationVisitor<ArgumentFilter<Double, Double>>, CompareFilter.SubjectVisitor<ArgumentFilter<?, ?>> { + + public static final ArgumentFilterFactoryImpl INSTANCE = new ArgumentFilterFactoryImpl(); + + private ArgumentFilterFactoryImpl() { + // singleton + } + + @Override + public ArgumentFilter<?, ?> createFilter(Filter<?, ?> filter) { + return filter.accept(this); + } + + @Override + public ArgumentFilter<?, ?> visit(TypeFilter<?, ?> filter) { + return filter.getInstanceOfLambda(); + } + + @Override + public ArgumentFilter<?, ?> visit(RTypeFilter<?> filter) { + if (filter.getType() == RType.Integer) { + return x -> x instanceof Integer || x instanceof RAbstractIntVector; + } else if (filter.getType() == RType.Double) { + return x -> x instanceof Double || x instanceof RAbstractDoubleVector; + } else if (filter.getType() == RType.Logical) { + return x -> 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; + } else if (filter.getType() == RType.Raw) { + return x -> x instanceof RAbstractRawVector; + } else { + throw RInternalError.unimplemented("TODO: more types here"); + } + } + + @Override + public ArgumentFilter<?, ?> visit(CompareFilter<?> filter) { + return filter.getSubject().accept(this, filter.getOperation()); + } + + @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); + } + }; + } + + @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); + } + }; + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Override + public ArgumentFilter<?, ?> visit(NotFilter<?> filter) { + ArgumentFilter toNegate = filter.getFilter().accept(this); + return (ArgumentFilter<Object, Object>) arg -> !toNegate.test(arg); + } + + @Override + public ArgumentFilter<?, ?> visit(MatrixFilter<?> filter) { + return filter.acceptOperation(this); + } + + @Override + public ArgumentFilter<?, ?> visit(DoubleFilter filter) { + return filter.acceptOperation(this); + } + + @Override + public ArgumentFilter<RAbstractVector, RAbstractVector> visitIsMatrix() { + return RAbstractVector::isMatrix; + } + + @Override + public ArgumentFilter<RAbstractVector, RAbstractVector> visitIsSquareMatrix() { + return x -> x.isMatrix() && x.getDimensions()[0] == x.getDimensions()[1]; + } + + @Override + public ArgumentFilter<Double, Double> visitIsFinite() { + return x -> !Double.isInfinite(x); + } + + @Override + public ArgumentFilter<Double, Double> visitIsFractional() { + return x -> !RRuntime.isNAorNaN(x) && !Double.isInfinite(x) && x != Math.floor(x); + } + + @Override + public ArgumentFilter<?, ?> visit(ScalarValue scalarValue, byte operation) { + switch (operation) { + case CompareFilter.EQ: + switch (scalarValue.type) { + case Character: + return (String arg) -> arg.equals(scalarValue.value); + case Integer: + return (Integer arg) -> arg == (int) scalarValue.value; + case Double: + return (Double arg) -> arg == (double) scalarValue.value; + case Logical: + return (Byte arg) -> arg == (byte) scalarValue.value; + case Any: + return arg -> arg.equals(scalarValue.value); + default: + throw RInternalError.unimplemented("TODO: more types here "); + } + case CompareFilter.GT: + switch (scalarValue.type) { + case Integer: + return (Integer arg) -> arg > (int) scalarValue.value; + case Double: + return (Double arg) -> arg > (double) scalarValue.value; + case Logical: + return (Byte arg) -> arg > (byte) scalarValue.value; + default: + throw RInternalError.unimplemented("TODO: more types here"); + } + case CompareFilter.LT: + switch (scalarValue.type) { + case Integer: + return (Integer arg) -> arg < (int) scalarValue.value; + case Double: + return (Double arg) -> arg < (double) scalarValue.value; + case Logical: + return (Byte arg) -> arg < (byte) scalarValue.value; + default: + throw RInternalError.unimplemented("TODO: more types here"); + } + case CompareFilter.GE: + switch (scalarValue.type) { + case Integer: + return (Integer arg) -> arg >= (int) scalarValue.value; + case Double: + return (Double arg) -> arg >= (double) scalarValue.value; + case Logical: + return (Byte arg) -> arg >= (byte) scalarValue.value; + default: + throw RInternalError.unimplemented("TODO: more types here"); + } + case CompareFilter.LE: + switch (scalarValue.type) { + case Integer: + return (Integer arg) -> arg <= (int) scalarValue.value; + case Double: + return (Double arg) -> arg <= (double) scalarValue.value; + case Logical: + return (Byte arg) -> arg <= (byte) scalarValue.value; + default: + throw RInternalError.unimplemented("TODO: more types here"); + } + case CompareFilter.SAME: + return arg -> arg == scalarValue.value; + + default: + throw RInternalError.unimplemented("TODO: more operations here"); + } + } + + @Override + public ArgumentFilter<?, ?> visit(NATest naTest, byte operation) { + switch (operation) { + case CompareFilter.EQ: + switch (naTest.type) { + case Integer: + return arg -> RRuntime.isNA((int) arg); + case Double: + return arg -> RRuntime.isNAorNaN((double) arg); + case Logical: + return arg -> RRuntime.isNA((byte) arg); + case Character: + return arg -> RRuntime.isNA((String) arg); + case Complex: + return arg -> RRuntime.isNA((RComplex) arg); + default: + throw RInternalError.unimplemented("TODO: more types here"); + } + default: + throw RInternalError.unimplemented("TODO: more operations here"); + } + } + + @Override + public ArgumentFilter<String, String> visit(StringLength stringLength, byte operation) { + switch (operation) { + case CompareFilter.EQ: + return arg -> arg.length() == stringLength.length; + + case CompareFilter.GT: + return arg -> arg.length() > stringLength.length; + + case CompareFilter.LT: + return arg -> arg.length() < stringLength.length; + + case CompareFilter.GE: + return arg -> arg.length() >= stringLength.length; + + case CompareFilter.LE: + return arg -> arg.length() <= stringLength.length; + + default: + throw RInternalError.unimplemented("TODO: more operations here"); + } + } + + @Override + public ArgumentFilter<RAbstractVector, RAbstractVector> visit(VectorSize vectorSize, byte operation) { + switch (operation) { + case CompareFilter.EQ: + return arg -> arg.getLength() == vectorSize.size; + + case CompareFilter.GT: + return arg -> arg.getLength() > vectorSize.size; + + case CompareFilter.LT: + return arg -> arg.getLength() < vectorSize.size; + + case CompareFilter.GE: + return arg -> arg.getLength() >= vectorSize.size; + + case CompareFilter.LE: + return arg -> arg.getLength() <= vectorSize.size; + + default: + throw RInternalError.unimplemented("TODO: more operations here"); + } + } + + @Override + public ArgumentFilter<RAbstractVector, RAbstractVector> visit(ElementAt elementAt, byte operation) { + switch (operation) { + case CompareFilter.EQ: + switch (elementAt.type) { + case Integer: + return arg -> elementAt.index < arg.getLength() && (int) elementAt.value == (int) arg.getDataAtAsObject(elementAt.index); + case Double: + return arg -> elementAt.index < arg.getLength() && (double) elementAt.value == (double) arg.getDataAtAsObject(elementAt.index); + case Logical: + return arg -> elementAt.index < arg.getLength() && (byte) elementAt.value == (byte) arg.getDataAtAsObject(elementAt.index); + case Character: + case Complex: + return arg -> elementAt.index < arg.getLength() && elementAt.value.equals(arg.getDataAtAsObject(elementAt.index)); + default: + throw RInternalError.unimplemented("TODO: more types here"); + } + default: + throw RInternalError.unimplemented("TODO: more operations here"); + } + } + + @Override + public ArgumentFilter<RAbstractVector, RAbstractVector> visit(Dim dim, byte operation) { + switch (operation) { + case CompareFilter.EQ: + return v -> v.isMatrix() && v.getDimensions().length > dim.dimIndex && v.getDimensions()[dim.dimIndex] == dim.dimSize; + case CompareFilter.GT: + return v -> v.isMatrix() && v.getDimensions().length > dim.dimIndex && v.getDimensions()[dim.dimIndex] > dim.dimSize; + default: + throw RInternalError.unimplemented("TODO: more operations here"); + } + } + + } + + public interface ArgumentMapperFactory { + ArgumentMapper<?, ?> createMapper(Mapper<?, ?> mapper); + } + + public static final class ArgumentMapperFactoryImpl implements ArgumentMapperFactory, MapperVisitor<ValuePredicateArgumentMapper<Object, Object>> { + + public static final ArgumentMapperFactoryImpl INSTANCE = new ArgumentMapperFactoryImpl(); + + private ArgumentMapperFactoryImpl() { + // singleton + } + + @Override + public ArgumentMapper<Object, Object> createMapper(Mapper<?, ?> mapper) { + return mapper.accept(this); + } + + @Override + public ValuePredicateArgumentMapper<Object, Object> visit(MapToValue<?, ?> mapper) { + 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)); + } + + @Override + public ValuePredicateArgumentMapper<Object, Object> visit(MapDoubleToInt mapper) { + final NACheck naCheck = NACheck.create(); + return ValuePredicateArgumentMapper.fromLambda(x -> { + double d = (Double) x; + naCheck.enable(d); + return naCheck.convertDoubleToInt(d); + }); + } + + @Override + public ValuePredicateArgumentMapper<Object, Object> visit(MapToCharAt mapper) { + final int defaultValue = mapper.getDefaultValue(); + final int index = mapper.getIndex(); + return ValuePredicateArgumentMapper.fromLambda(x -> { + String str = (String) x; + if (x == null || str.isEmpty()) { + return defaultValue; + } else { + if (x == RRuntime.STRING_NA) { + return RRuntime.INT_NA; + } else { + return (int) str.charAt(index); + } + } + }); + } + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..3811fe65a1a8c14bd7f061d0f9b35a05eded4909 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java @@ -0,0 +1,82 @@ +/* + * 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.builtin.casts.fluent; + +import java.util.function.Function; + +import com.oracle.truffle.r.nodes.builtin.casts.Filter; +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 + * the pipeline building, i.e. in {@link InitialPhaseBuilder}. + */ +@SuppressWarnings("unchecked") +public class ArgCastBuilder<T, THIS> { + + private final PipelineBuilder builder; + + public ArgCastBuilder(PipelineBuilder builder) { + this.builder = builder; + } + + public PipelineBuilder pipelineBuilder() { + 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); + return (THIS) this; + } + + public <R, THAT extends ArgCastBuilder<R, THAT>> THAT alias(Function<THIS, THAT> aliaser) { + return aliaser.apply((THIS) this); + } + +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ChainBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ChainBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..d52c46dbbee74036e15cbbd0781a532711136801 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ChainBuilder.java @@ -0,0 +1,72 @@ +/* + * 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.builtin.casts.fluent; + +import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep; + +/** + * Holds a chain of {@link PipelineStep} instances, allows to add new steps at the end. This class + * can be used to create a chain outside of a context of {@link PipelineBuilder}, it can be + * constructed using the {@code chain} method from {@code Predef}. + * + * @see Predef#chain + */ +public final class ChainBuilder<T> { + private final PipelineStep<?, ?> firstStep; + private PipelineStep<?, ?> lastStep; + + // TODO: can be package private once Predef is moved to fluent package + public ChainBuilder(PipelineStep<?, ?> firstStep) { + assert firstStep != null : "firstStep must not be null"; + this.firstStep = firstStep; + lastStep = firstStep; + } + + PipelineStep<?, ?> getFirstStep() { + return firstStep; + } + + void addStep(PipelineStep<?, ?> nextStep) { + lastStep.setNext(nextStep); + lastStep = nextStep; + } + + @SuppressWarnings("overloads") + public ChainBuilder<T> with(PipelineStep<?, ?> nextStep) { + addStep(nextStep); + return this; + } + + @SuppressWarnings("overloads") + public ChainBuilder<T> with(Mapper<?, ?> mapper) { + addStep(new MapStep<>(mapper)); + return this; + } + + public PipelineStep<?, ?> end() { + return firstStep; + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..016eef5e7a23b0e94f1a0679722288ce5dd11493 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java @@ -0,0 +1,105 @@ +/* + * 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.builtin.casts.fluent; + +import com.oracle.truffle.r.nodes.builtin.casts.Filter; +import com.oracle.truffle.r.runtime.RError; +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 + * specific type. Any method that represents casting or mapping of the argument to a another + * specific type returns different instance of {@link CoercedPhaseBuilder} with its generic + * parameters set accordingly. Methods that map vectors to single element return + * {@link HeadPhaseBuilder}. + */ +public final class CoercedPhaseBuilder<T extends RAbstractVector, S> extends ArgCastBuilder<T, CoercedPhaseBuilder<T, S>> { + + private final Class<?> elementClass; + + public CoercedPhaseBuilder(PipelineBuilder builder, Class<?> elementClass) { + super(builder); + this.elementClass = elementClass; + } + + /** + * The inserted cast node returns the default value if the input vector is empty. It also + * 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); + return new HeadPhaseBuilder<>(pipelineBuilder()); + } + + /** + * 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); + return new HeadPhaseBuilder<>(pipelineBuilder()); + } + + /** + * The inserted cast node raises the public error, if defined, or RError.Message.LENGTH_ZERO + * error if the input vector is empty. + */ + public HeadPhaseBuilder<S> findFirst() { + pipelineBuilder().appendFindFirst(null, elementClass, null, null, null); + return new HeadPhaseBuilder<>(pipelineBuilder()); + } + + /** + * The inserted cast node returns the default value if the input vector is empty. It reports no + * warning message. + */ + public HeadPhaseBuilder<S> findFirst(S defaultValue) { + assert defaultValue != null : "defaultValue cannot be null"; + pipelineBuilder().appendFindFirst(defaultValue, elementClass, null, 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); + return this; + } + + public CoercedPhaseBuilder<T, S> mustBe(Filter<? super T, ? extends T> argFilter) { + return mustBe(argFilter, null, null, (Object[]) null); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..28c5619018f95fbb8cd9596bc4576723626a9c57 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/FindFirstNodeBuilder.java @@ -0,0 +1,104 @@ +/* + * 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.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; +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; + + public FindFirstNodeBuilder(RBaseNode callObj, Message message, Object[] messageArgs) { + this.callObj = callObj; + 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)); + } + + public PipelineStep<RAbstractLogicalVector, Byte> logicalElement() { + return create(Byte.class, null); + } + + public PipelineStep<RAbstractLogicalVector, Byte> logicalElement(byte defaultValue) { + return create(Byte.class, defaultValue); + } + + public PipelineStep<RAbstractDoubleVector, Double> doubleElement() { + return create(Double.class, null); + } + + public PipelineStep<RAbstractDoubleVector, Double> doubleElement(double defaultValue) { + return create(Double.class, defaultValue); + } + + public PipelineStep<RAbstractIntVector, Integer> integerElement() { + return create(Integer.class, null); + } + + public PipelineStep<RAbstractIntVector, Integer> integerElement(int defaultValue) { + return create(Integer.class, defaultValue); + } + + public PipelineStep<RAbstractStringVector, String> stringElement() { + return create(String.class, null); + } + + public PipelineStep<RAbstractStringVector, String> stringElement(String defaultValue) { + return create(String.class, defaultValue); + } + + public PipelineStep<RAbstractComplexVector, RComplex> complexElement() { + return create(String.class, null); + } + + public PipelineStep<RAbstractComplexVector, RComplex> complexElement(RComplex defaultValue) { + return create(String.class, defaultValue); + } + + public PipelineStep<RAbstractVector, Object> objectElement() { + return create(Object.class, null); + } + + public PipelineStep<RAbstractVector, Object> objectElement(Object defaultValue) { + return create(Object.class, defaultValue); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..c4c3a362e60a82a424c75a505ee01aca9c351561 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java @@ -0,0 +1,138 @@ +/* + * 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.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.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. + */ +public final class HeadPhaseBuilder<T> extends ArgCastBuilder<T, HeadPhaseBuilder<T>> { + + public HeadPhaseBuilder(PipelineBuilder builder) { + super(builder); + } + + public <S> HeadPhaseBuilder<S> map(Mapper<T, S> mapFn) { + // state().castBuilder().insert(state().index(), () -> MapNode.create(mapFn)); + pipelineBuilder().appendMap(mapFn); + return new HeadPhaseBuilder<>(pipelineBuilder()); + } + + public <S extends T, R> HeadPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper) { + pipelineBuilder().appendMapIf(argFilter, trueBranchMapper); + return new HeadPhaseBuilder<>(pipelineBuilder()); + } + + 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); + return new HeadPhaseBuilder<>(pipelineBuilder()); + } + + public <S extends T, R> HeadPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, PipelineStep<S, ?> trueBranch) { + pipelineBuilder().appendMapIf(argFilter, trueBranch); + return new HeadPhaseBuilder<>(pipelineBuilder()); + } + + 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); + 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()); + } + + 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()); + } + + public <S extends T> HeadPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter) { + return mustBe(argFilter, null, null, (Object[]) null); + } + + 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()); + } + + 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()); + } + + public <S> HeadPhaseBuilder<S> shouldBe(Class<S> cls, RError.Message message, Object... messageArgs) { + shouldBe(Predef.instanceOf(cls), message, messageArgs); + return new HeadPhaseBuilder<>(pipelineBuilder()); + } + + 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; + } + + public HeadPhaseBuilder<T> notNA(T naReplacement, RBaseNode callObj, RError.Message message, Object... messageArgs) { + pipelineBuilder().appendNotNA(naReplacement, callObj, message, messageArgs); + return this; + } + + public HeadPhaseBuilder<T> notNA(T naReplacement, RError.Message message, Object... messageArgs) { + pipelineBuilder().appendNotNA(naReplacement, null, message, messageArgs); + return this; + } + + public HeadPhaseBuilder<T> notNA() { + pipelineBuilder().appendNotNA(null, null, null, null); + return this; + } + + public HeadPhaseBuilder<T> notNA(T naReplacement) { + pipelineBuilder().appendNotNA(naReplacement, null, 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 new file mode 100644 index 0000000000000000000000000000000000000000..bec9e0943e38390c5ec2f598f6edd3255ecc0949 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java @@ -0,0 +1,217 @@ +/* + * 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.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.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.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RRaw; +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.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. + */ +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); + } + + 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()); + } + + 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()); + } + + 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()); + } + + public <S> InitialPhaseBuilder<S> shouldBe(Class<S> cls, RError.Message message, Object... messageArgs) { + shouldBe(Predef.instanceOf(cls), message, messageArgs); + return new InitialPhaseBuilder<>(pipelineBuilder()); + } + + public <S> InitialPhaseBuilder<S> shouldBe(Class<S> cls) { + shouldBe(Predef.instanceOf(cls)); + return new InitialPhaseBuilder<>(pipelineBuilder()); + } + + public <S> InitialPhaseBuilder<S> map(Mapper<T, S> mapFn) { + pipelineBuilder().appendMap(mapFn); + return new InitialPhaseBuilder<>(pipelineBuilder()); + } + + public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper) { + pipelineBuilder().appendMapIf(argFilter, trueBranchMapper); + return new InitialPhaseBuilder<>(pipelineBuilder()); + } + + public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper, Mapper<T, ?> falseBranchMapper) { + pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, falseBranchMapper); + return new InitialPhaseBuilder<>(pipelineBuilder()); + } + + public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, PipelineStep<?, ?> trueBranch) { + pipelineBuilder().appendMapIf(argFilter, trueBranch); + return new InitialPhaseBuilder<>(pipelineBuilder()); + } + + public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, PipelineStep<?, ?> trueBranch, PipelineStep<?, ?> falseBranch) { + pipelineBuilder().appendMapIf(argFilter, trueBranch, falseBranch); + return new InitialPhaseBuilder<>(pipelineBuilder()); + } + + public InitialPhaseBuilder<T> notNA(RBaseNode callObj, RError.Message message, Object... messageArgs) { + pipelineBuilder().appendNotNA(null, callObj, message, messageArgs); + return this; + } + + public InitialPhaseBuilder<T> notNA(RError.Message message, Object... messageArgs) { + pipelineBuilder().appendNotNA(null, null, 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); + return this; + } + + public InitialPhaseBuilder<T> boxPrimitive() { + pipelineBuilder().appendBoxPrimitive(); + return this; + } + + public CoercedPhaseBuilder<RAbstractIntVector, Integer> asIntegerVector(boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { + pipelineBuilder().appendAsIntegerVector(preserveNames, dimensionsPreservation, attrPreservation); + return new CoercedPhaseBuilder<>(pipelineBuilder(), Integer.class); + } + + public CoercedPhaseBuilder<RAbstractIntVector, Integer> asIntegerVector() { + return asIntegerVector(false, false, false); + } + + public CoercedPhaseBuilder<RAbstractDoubleVector, Double> asDoubleVector(boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { + pipelineBuilder().appendAsDoubleVector(preserveNames, dimensionsPreservation, attrPreservation); + return new CoercedPhaseBuilder<>(pipelineBuilder(), Double.class); + } + + public CoercedPhaseBuilder<RAbstractDoubleVector, Double> asDoubleVector() { + return asDoubleVector(false, false, false); + } + + public CoercedPhaseBuilder<RAbstractDoubleVector, Byte> asLogicalVector(boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { + pipelineBuilder().appendAsLogicalVector(preserveNames, dimensionsPreservation, attrPreservation); + return new CoercedPhaseBuilder<>(pipelineBuilder(), Byte.class); + } + + public CoercedPhaseBuilder<RAbstractDoubleVector, Byte> asLogicalVector() { + return asLogicalVector(false, false, false); + } + + public CoercedPhaseBuilder<RAbstractStringVector, String> asStringVector(boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { + pipelineBuilder().appendAsStringVector(preserveNames, dimensionsPreservation, attrPreservation); + return new CoercedPhaseBuilder<>(pipelineBuilder(), String.class); + } + + public CoercedPhaseBuilder<RAbstractStringVector, String> asStringVector() { + pipelineBuilder().appendAsStringVector(); + return new CoercedPhaseBuilder<>(pipelineBuilder(), String.class); + } + + public CoercedPhaseBuilder<RAbstractComplexVector, RComplex> asComplexVector() { + pipelineBuilder().appendAsComplexVector(); + return new CoercedPhaseBuilder<>(pipelineBuilder(), RComplex.class); + } + + public CoercedPhaseBuilder<RAbstractRawVector, RRaw> asRawVector() { + pipelineBuilder().appendAsRawVector(); + return new CoercedPhaseBuilder<>(pipelineBuilder(), RRaw.class); + } + + public CoercedPhaseBuilder<RAbstractVector, Object> asVector() { + pipelineBuilder().appendAsVector(); + return new CoercedPhaseBuilder<>(pipelineBuilder(), Object.class); + } + + public CoercedPhaseBuilder<RAbstractVector, Object> asVector(boolean preserveNonVector) { + 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); + return new CoercedPhaseBuilder<>(pipelineBuilder(), Object.class); + } + + public HeadPhaseBuilder<RAttributable> asAttributable(boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { + pipelineBuilder().appendAsAttributable(preserveNames, dimensionsPreservation, attrPreservation); + return new HeadPhaseBuilder<>(pipelineBuilder()); + } + +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..d94cda9d6252bd54f651fa854de6e91ea3be13ad --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java @@ -0,0 +1,168 @@ +/* + * 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.builtin.casts.fluent; + +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; +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.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 + * created so far and some data related to the selected argument for which we are creating the + * pipeline. + */ +public final class PipelineBuilder { + + private final PipelineConfigBuilder pcb; + private ChainBuilder<?> chainBuilder; + + public PipelineBuilder(PipelineConfigBuilder pcb) { + this.pcb = pcb; + } + + // TODO: can be package private once the legacy API is removed + public void append(PipelineStep<?, ?> step) { + if (chainBuilder == null) { + chainBuilder = new ChainBuilder<>(step); + } else { + chainBuilder.addStep(step); + } + } + + public PipelineConfigBuilder getPipelineConfig() { + return pcb; + } + + public PipelineStep<?, ?> getFirstStep() { + return chainBuilder != null ? chainBuilder.getFirstStep() : null; + } + + public void appendBoxPrimitive() { + 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 appendAsAttributable(boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { + append(new AttributableCoercionStep<>(preserveNames, dimensionsPreservation, attrPreservation)); + } + + public void appendAsVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean preserveNonVector) { + append(new CoercionStep<>(RType.Any, true, preserveNames, preserveDimensions, preserveAttributes, preserveNonVector)); + } + + public void appendAsVector() { + appendAsVector(false, false, false, true); + } + + public void appendAsRawVector() { + append(new CoercionStep<>(RType.Raw, true, false, false, false)); + } + + public void appendAsComplexVector() { + append(new CoercionStep<>(RType.Complex, true, false, false, false)); + } + + public void appendAsStringVector(boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { + append(new CoercionStep<>(RType.Character, true, preserveNames, dimensionsPreservation, attrPreservation)); + } + + public void appendAsStringVector() { + append(new CoercionStep<>(RType.Character, true, false, false, false)); + } + + public void appendAsLogicalVector(boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { + append(new CoercionStep<>(RType.Logical, true, preserveNames, dimensionsPreservation, attrPreservation)); + } + + public void appendAsDoubleVector(boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { + append(new CoercionStep<>(RType.Double, true, preserveNames, dimensionsPreservation, attrPreservation)); + } + + public void appendAsIntegerVector(boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) { + append(new CoercionStep<>(RType.Integer, true, preserveNames, dimensionsPreservation, attrPreservation)); + } + + public void appendNotNA(Object naReplacement, RBaseNode callObj, Message message, Object[] messageArgs) { + append(new NotNAStep<>(naReplacement, createMessage(callObj, message, messageArgs))); + } + + public void appendMapIf(Filter<?, ?> argFilter, Mapper<?, ?> trueBranchMapper) { + appendMapIf(argFilter, trueBranchMapper, null); + } + + public void appendMapIf(Filter<?, ?> argFilter, Mapper<?, ?> trueBranchMapper, Mapper<?, ?> falseBranchMapper) { + appendMapIf(argFilter, new MapStep<>(trueBranchMapper), falseBranchMapper == null ? null : new MapStep<>(falseBranchMapper)); + } + + public void appendMapIf(Filter<?, ?> argFilter, PipelineStep<?, ?> trueBranch) { + appendMapIf(argFilter, trueBranch, null); + } + + public void appendMapIf(Filter<?, ?> argFilter, PipelineStep<?, ?> trueBranch, PipelineStep<?, ?> falseBranch) { + append(new MapIfStep<>(argFilter, trueBranch, falseBranch)); + } + + public void appendMap(Mapper<?, ?> mapFn) { + 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 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)); + } + + 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); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..79fd4651d2c321223ea9ad81679ef4e6ba7228ee --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java @@ -0,0 +1,129 @@ +/* + * 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.builtin.casts.fluent; + +import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; +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; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; + +/** + * Provides fluent API for building the pipeline configuration {@link PipelineConfig}: default + * error/warning message and handling of {@link RNull} and {@link RMissing}. + */ +public final class PipelineConfigBuilder { + + private final String argumentName; + private MessageData defaultError; + private MessageData defaultWarning; + + private Mapper<? super RMissing, ?> missingMapper; + private Mapper<? super RNull, ?> nullMapper; + private MessageData missingMsg; + private MessageData nullMsg; + + // TODO: to be removed with legacy API + private boolean wasLegacyAsVectorCall = false; + + public PipelineConfigBuilder(String argumentName) { + this.argumentName = argumentName; + defaultError = new MessageData(null, RError.Message.INVALID_ARGUMENT, argumentName); + defaultWarning = defaultError; + } + + public PipelineConfig build() { + return new PipelineConfig(argumentName, defaultError, defaultWarning, missingMapper, nullMapper, missingMsg, nullMsg); + } + + public void setWasLegacyAsVectorCall() { + wasLegacyAsVectorCall = true; + } + + public boolean wasLegacyAsVectorCall() { + return wasLegacyAsVectorCall; + } + + void setDefaultError(MessageData defaultError) { + this.defaultError = defaultError; + } + + void setDefaultWarning(MessageData defaultWarning) { + this.defaultWarning = defaultWarning; + } + + public PipelineConfigBuilder mustNotBeMissing(RBaseNode callObj, RError.Message errorMsg, Object... msgArgs) { + missingMapper = null; + missingMsg = new MessageData(callObj, errorMsg, msgArgs); + return this; + } + + public PipelineConfigBuilder mapMissing(Mapper<? super RMissing, ?> mapper) { + missingMapper = mapper; + missingMsg = null; + return this; + } + + public PipelineConfigBuilder mapMissing(Mapper<? super RMissing, ?> mapper, RBaseNode callObj, RError.Message warningMsg, Object... msgArgs) { + missingMapper = mapper; + missingMsg = new MessageData(callObj, warningMsg, msgArgs); + return this; + } + + public PipelineConfigBuilder allowMissing() { + return mapMissing(Predef.missingConstant()); + } + + public PipelineConfigBuilder allowMissing(RBaseNode callObj, RError.Message warningMsg, Object... msgArgs) { + return mapMissing(Predef.missingConstant(), callObj, warningMsg, msgArgs); + } + + public PipelineConfigBuilder mustNotBeNull(RBaseNode callObj, RError.Message errorMsg, Object... msgArgs) { + nullMapper = null; + nullMsg = new MessageData(callObj, errorMsg, msgArgs); + return this; + } + + public PipelineConfigBuilder mapNull(Mapper<? super RNull, ?> mapper) { + nullMapper = mapper; + nullMsg = null; + return this; + } + + public PipelineConfigBuilder mapNull(Mapper<? super RNull, ?> mapper, RBaseNode callObj, RError.Message warningMsg, Object... msgArgs) { + nullMapper = mapper; + nullMsg = new MessageData(callObj, warningMsg, msgArgs); + return this; + } + + public PipelineConfigBuilder allowNull() { + return mapNull(Predef.nullConstant()); + } + + public PipelineConfigBuilder allowNull(RBaseNode callObj, RError.Message warningMsg, Object... msgArgs) { + return mapNull(Predef.nullConstant(), callObj, warningMsg, msgArgs); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..d2feefa58d6fc4be0af1cf035d8551df077506f7 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java @@ -0,0 +1,117 @@ +/* + * 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.builtin.casts.fluent; + +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. + * 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, + * there is no way to invoke configuration related methods defined here. + */ +public final class PreinitialPhaseBuilder<T> extends InitialPhaseBuilder<T> { + + public PreinitialPhaseBuilder(PipelineBuilder pipelineBuilder) { + super(pipelineBuilder); + } + + public PreinitialPhaseBuilder<T> conf(Consumer<PipelineConfigBuilder> cfgLambda) { + cfgLambda.accept(pipelineBuilder().getPipelineConfig()); + return this; + } + + public InitialPhaseBuilder<T> allowNull() { + return conf(c -> c.allowNull()); + } + + public InitialPhaseBuilder<T> mustNotBeNull() { + return conf(c -> c.mustNotBeNull(null, null, (Object[]) null)); + } + + public InitialPhaseBuilder<T> mustNotBeNull(RError.Message errorMsg, Object... msgArgs) { + return conf(c -> c.mustNotBeNull(null, errorMsg, msgArgs)); + } + + public InitialPhaseBuilder<T> mustNotBeNull(RBaseNode callObj, RError.Message errorMsg, Object... msgArgs) { + return conf(c -> c.mustNotBeNull(callObj, errorMsg, msgArgs)); + } + + public InitialPhaseBuilder<T> mapNull(Mapper<? super RNull, ?> mapper) { + return conf(c -> c.mapNull(mapper)); + } + + public InitialPhaseBuilder<T> allowMissing() { + return conf(c -> c.allowMissing()); + } + + public InitialPhaseBuilder<T> mustNotBeMissing() { + return conf(c -> c.mustNotBeMissing(null, null, (Object[]) null)); + } + + public InitialPhaseBuilder<T> mustNotBeMissing(RError.Message errorMsg, Object... msgArgs) { + return conf(c -> c.mustNotBeMissing(null, errorMsg, msgArgs)); + } + + public InitialPhaseBuilder<T> mustNotBeMissing(RBaseNode callObj, RError.Message errorMsg, Object... msgArgs) { + return conf(c -> c.mustNotBeMissing(callObj, errorMsg, msgArgs)); + } + + public InitialPhaseBuilder<T> mapMissing(Mapper<? super RMissing, ?> mapper) { + return conf(c -> c.mapMissing(mapper)); + } + + public InitialPhaseBuilder<T> allowNullAndMissing() { + return conf(c -> c.allowMissing().allowNull()); + } + + @Override + public PreinitialPhaseBuilder<T> defaultError(RBaseNode callObj, RError.Message message, Object... args) { + pipelineBuilder().getPipelineConfig().setDefaultError(new MessageData(callObj, message, args)); + pipelineBuilder().appendDefaultErrorStep(callObj, message, args); + return this; + } + + @Override + public PreinitialPhaseBuilder<T> defaultError(Message message, Object... args) { + defaultError(null, message, args); + return this; + } + + @Override + public PreinitialPhaseBuilder<T> defaultWarning(RBaseNode callObj, Message message, Object... args) { + pipelineBuilder().getPipelineConfig().setDefaultWarning(new MessageData(callObj, message, args)); + pipelineBuilder().appendDefaultWarningStep(callObj, 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 0adccc729521bcd0f6769db5810f256da7bc444d..601e051b4b2053f850e111a6965d558d01b0f341 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 @@ -26,11 +26,9 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.nodes.RASTUtils; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RSerialize; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; @@ -46,6 +44,7 @@ public final class BlockNode extends RSourceSectionNode implements RSyntaxNode, public static final RNode[] EMPTY_BLOCK = new RNode[0]; @Children protected final RNode[] sequence; + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); public BlockNode(SourceSection src, RNode[] sequence) { super(src); @@ -59,7 +58,7 @@ public final class BlockNode extends RSourceSectionNode implements RSyntaxNode, @Override @ExplodeLoop public Object execute(VirtualFrame frame) { - RContext.getInstance().setVisible(true); + visibility.execute(frame, true); Object lastResult = RNull.instance; for (int i = 0; i < sequence.length; i++) { lastResult = sequence[i].execute(frame); @@ -67,18 +66,6 @@ public final class BlockNode extends RSourceSectionNode implements RSyntaxNode, return lastResult; } - @Override - public void serializeImpl(RSerialize.State state) { - state.setAsLangType(); - state.setCarAsSymbol("{"); - - for (int i = 0; i < sequence.length; i++) { - state.openPairList(SEXPTYPE.LISTSXP); - state.serializeNodeSetCar(sequence[i]); - } - state.linkPairList(sequence.length + 1); - } - @Override public RSyntaxElement getSyntaxLHS() { return RSyntaxLookup.createDummyLookup(getSourceSection(), "{", true); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BreakNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BreakNode.java index 3479f87c3a917a82fd38fe3e6c2a241d83e2f004..b67d1e9001cf5411667f9d1888debf22bbb0a30a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BreakNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BreakNode.java @@ -24,9 +24,8 @@ package com.oracle.truffle.r.nodes.control; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RSerialize; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; @@ -35,18 +34,15 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; public final class BreakNode extends RSourceSectionNode implements RSyntaxNode, RSyntaxCall { + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); + public BreakNode(SourceSection src) { super(src); } - @Override - public void serializeImpl(RSerialize.State state) { - state.setAsBuiltin("break"); - } - @Override public Object execute(VirtualFrame frame) { - RContext.getInstance().setVisible(false); + visibility.execute(frame, false); throw BreakException.instance; } 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 2e29ed124561413cd7eadf5761589219c76e92d5..74ac26d6d429df11b2f91682f40432b0725278e4 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 @@ -36,12 +36,10 @@ import com.oracle.truffle.r.nodes.RRootNode; 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.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.AnonymousFrameVariable; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RSerialize; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RNull; -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.RSyntaxCall; @@ -55,6 +53,7 @@ public final class ForNode extends AbstractLoopNode implements RSyntaxNode, RSyn @Child private WriteVariableNode writeIndexNode; @Child private WriteVariableNode writeRangeNode; @Child private LoopNode loopNode; + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); private ForNode(SourceSection src, WriteVariableNode cvar, RNode range, RNode body) { super(src); @@ -79,7 +78,7 @@ public final class ForNode extends AbstractLoopNode implements RSyntaxNode, RSyn writeRangeNode.execute(frame); writeLengthNode.execute(frame); loopNode.executeLoop(frame); - RContext.getInstance().setVisible(false); + visibility.execute(frame, false); return RNull.instance; } @@ -95,22 +94,6 @@ public final class ForNode extends AbstractLoopNode implements RSyntaxNode, RSyn return getForRepeatingNode().body; } - @Override - public void serializeImpl(RSerialize.State state) { - state.setAsBuiltin("for"); - state.openPairList(SEXPTYPE.LISTSXP); - // variable - state.serializeNodeSetCar(getCvar()); - // range - state.openPairList(SEXPTYPE.LISTSXP); - state.serializeNodeSetCar(getRange()); - // body - state.openPairList(SEXPTYPE.LISTSXP); - state.serializeNodeSetCar(getBody()); - state.linkPairList(3); - state.setCdr(state.closePairList()); - } - private ForRepeatingNode getForRepeatingNode() { return (ForRepeatingNode) loopNode.getRepeatingNode(); } 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 25ece0e792df83744f8a0bd50af5943889eb1767..a5d40486f43afdf2c4d364d4754ce7303185411b 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 @@ -26,14 +26,12 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.nodes.unary.ConvertBooleanNode; 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.RSerialize; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; @@ -46,6 +44,7 @@ public final class IfNode extends RSourceSectionNode implements RSyntaxNode, RSy @Child private ConvertBooleanNode condition; @Child private RNode thenPart; @Child private RNode elsePart; + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); private final ConditionProfile conditionProfile = ConditionProfile.createCountingProfile(); @@ -72,7 +71,7 @@ public final class IfNode extends RSourceSectionNode implements RSyntaxNode, RSy @Override public Object execute(VirtualFrame frame) { byte cond = condition.executeByte(frame); - RContext.getInstance().setVisible(elsePart != null || cond == RRuntime.LOGICAL_TRUE); + visibility.execute(frame, elsePart != null || cond == RRuntime.LOGICAL_TRUE); if (cond == RRuntime.LOGICAL_NA) { // NA is the only remaining option @@ -105,23 +104,6 @@ public final class IfNode extends RSourceSectionNode implements RSyntaxNode, RSy return elsePart; } - @Override - public void serializeImpl(RSerialize.State state) { - state.setAsBuiltin("if"); - state.openPairList(SEXPTYPE.LISTSXP); - // condition - state.serializeNodeSetCar(condition); - // then, with brace - state.openPairList(SEXPTYPE.LISTSXP); - state.serializeNodeSetCar(thenPart); - if (elsePart != null) { - state.openPairList(SEXPTYPE.LISTSXP); - state.serializeNodeSetCar(elsePart); - } - state.linkPairList(elsePart == null ? 2 : 3); - state.setCdr(state.closePairList()); - } - @Override public RSyntaxElement getSyntaxLHS() { return RSyntaxLookup.createDummyLookup(getSourceSection(), "if", true); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/NextNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/NextNode.java index dab24867943b464f7f4603239998327ab405f308..d4fb2410e75e0820607a984d10c7e7b449fd1335 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/NextNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/NextNode.java @@ -24,9 +24,8 @@ package com.oracle.truffle.r.nodes.control; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RSerialize; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; @@ -35,21 +34,18 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; public final class NextNode extends RSourceSectionNode implements RSyntaxNode, RSyntaxCall { + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); + public NextNode(SourceSection src) { super(src); } @Override public Object execute(VirtualFrame frame) { - RContext.getInstance().setVisible(false); + visibility.execute(frame, false); throw NextException.instance; } - @Override - public void serializeImpl(RSerialize.State state) { - state.setAsBuiltin("next"); - } - @Override public RSyntaxElement getSyntaxLHS() { return RSyntaxLookup.createDummyLookup(getSourceSection(), "next", true); 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 ab03b7d5e149f22fc2389975ac654331a7eac10e..4efcf6edff934be9b8391b74132ab867f4ada397 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 @@ -24,14 +24,16 @@ package com.oracle.truffle.r.nodes.control; import java.util.List; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.nodes.access.RemoveAndAnswerNode; import com.oracle.truffle.r.nodes.access.WriteVariableNode; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RSerialize; -import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; @@ -61,6 +63,7 @@ public final class ReplacementNode extends RSourceSectionNode implements RSyntax @Children private final RNode[] updates; @Child private RemoveAndAnswerNode removeTemp; @Child private RemoveAndAnswerNode removeRhs; + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); public ReplacementNode(SourceSection src, String operator, RSyntaxNode syntaxLhs, RSyntaxNode rhs, String rhsSymbol, RNode v, String tmpSymbol, List<RNode> updates) { super(src); @@ -98,19 +101,11 @@ public final class ReplacementNode extends RSourceSectionNode implements RSyntax update.execute(frame); } removeTemp.execute(frame); - return removeRhs.execute(frame); - } - - @Override - public void serializeImpl(RSerialize.State state) { - state.setAsLangType(); - state.setCarAsSymbol(operator); - state.openPairList(); - state.serializeNodeSetCar(syntaxLhs); - state.openPairList(SEXPTYPE.LISTSXP); - state.serializeNodeSetCar(storeRhs.getRhs()); - state.setCdr(state.closePairList()); - state.setCdr(state.closePairList()); + try { + return removeRhs.execute(frame); + } finally { + visibility.execute(frame, false); + } } @Override @@ -127,4 +122,41 @@ public final class ReplacementNode extends RSourceSectionNode implements RSyntax public ArgumentsSignature getSyntaxSignature() { return ArgumentsSignature.empty(2); } + + /** + * Used by the parser for assignments that miss a left hand side. This node will raise an error + * once executed. + */ + public static final class LHSError extends RSourceSectionNode implements RSyntaxNode, RSyntaxCall { + + private final String operator; + private final RSyntaxElement[] arguments; + + public LHSError(SourceSection sourceSection, String operator, RSyntaxElement[] arguments) { + super(sourceSection); + this.operator = operator; + this.arguments = arguments; + } + + @Override + public Object execute(VirtualFrame frame) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(this, Message.INVALID_LHS, "NULL"); + } + + @Override + public RSyntaxElement getSyntaxLHS() { + return RSyntaxLookup.createDummyLookup(null, operator, true); + } + + @Override + public RSyntaxElement[] getSyntaxArguments() { + return arguments; + } + + @Override + public ArgumentsSignature getSyntaxSignature() { + return ArgumentsSignature.empty(2); + } + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/WhileNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/WhileNode.java index 170a10ae5d85d3398f91ec1054ba4bc4b2daa325..fdff60e309eba202a05bfa647fc43cd13121eab2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/WhileNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/WhileNode.java @@ -31,13 +31,11 @@ import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.nodes.RRootNode; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.nodes.unary.ConvertBooleanNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RSerialize; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RNull; -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.RSyntaxCall; @@ -48,6 +46,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; public final class WhileNode extends AbstractLoopNode implements RSyntaxNode, RSyntaxCall { @Child private LoopNode loop; + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); /** * Also used for {@code repeat}, with a {@code TRUE} condition. @@ -68,7 +67,7 @@ public final class WhileNode extends AbstractLoopNode implements RSyntaxNode, RS @Override public Object execute(VirtualFrame frame) { loop.executeLoop(frame); - RContext.getInstance().setVisible(false); + visibility.execute(frame, false); return RNull.instance; } @@ -88,20 +87,6 @@ public final class WhileNode extends AbstractLoopNode implements RSyntaxNode, RS return isRepeat; } - @Override - public void serializeImpl(RSerialize.State state) { - state.setAsBuiltin(isRepeat ? "repeat" : "while"); - if (!isRepeat) { - state.openPairList(SEXPTYPE.LISTSXP); - // condition - state.serializeNodeSetCar(getCondition()); - } - state.openPairList(SEXPTYPE.LISTSXP); - state.serializeNodeSetCar(getBody()); - state.linkPairList(isRepeat ? 1 : 2); - state.setCdr(state.closePairList()); - } - private static final class WhileRepeatingNode extends RBaseNode implements RepeatingNode { @Child private ConvertBooleanNode condition; 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 a45022312ca4653b6c161b8c0734e45354ef3108..f600dd260b59b01622b64f07457435d412e2974c 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 @@ -65,49 +65,51 @@ public abstract class ArgumentStatePush extends Node { public void transitionState(VirtualFrame frame, RShareable shareable) { if (isRefCountUpdateable.profile(!shareable.isSharedPermanent())) { shareable.incRefCount(); - } - if (!FastROptions.RefCountIncrementOnly.getBooleanValue()) { - if (mask == 0) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - if (shareable instanceof RAbstractContainer) { - if (shareable instanceof RLanguage || ((RAbstractContainer) shareable).getLength() < REF_COUNT_SIZE_THRESHOLD) { - // don't decrement ref count for small objects or language objects- this is - // pretty conservative and can be further finessed + if (!FastROptions.RefCountIncrementOnly.getBooleanValue()) { + if (mask == 0) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + if (shareable instanceof RAbstractContainer) { + if (shareable instanceof RLanguage || ((RAbstractContainer) shareable).getLength() < REF_COUNT_SIZE_THRESHOLD) { + // don't decrement ref count for small objects or language objects- this + // is + // pretty conservative and can be further finessed + mask = -1; + return; + } + } + RFunction fun = RArguments.getFunction(frame); + if (fun == null) { mask = -1; return; } + Object root = fun.getRootNode(); + if (!(root instanceof FunctionDefinitionNode)) { + // root is RBuiltinRootNode + mask = -1; + return; + } + FunctionDefinitionNode fdn = (FunctionDefinitionNode) root; + PostProcessArgumentsNode postProcessNode = fdn.getArgPostProcess(); + if (postProcessNode == null) { + // arguments to this function are not to be reference counted + mask = -1; + return; + } + // this is needed for when FunctionDefinitionNode is split by the Truffle + // runtime + postProcessNode = postProcessNode.getActualNode(); + if (index >= Math.min(postProcessNode.getLength(), MAX_COUNTED_ARGS)) { + mask = -1; + return; + } + mask = 1 << index; + int transArgsBitSet = postProcessNode.transArgsBitSet; + postProcessNode.transArgsBitSet = transArgsBitSet | mask; + writeArgNode = insert(WriteLocalFrameVariableNode.createForRefCount(Integer.valueOf(mask))); } - RFunction fun = RArguments.getFunction(frame); - if (fun == null) { - mask = -1; - return; - } - Object root = fun.getRootNode(); - if (!(root instanceof FunctionDefinitionNode)) { - // root is RBuiltinRootNode - mask = -1; - return; - } - FunctionDefinitionNode fdn = (FunctionDefinitionNode) root; - PostProcessArgumentsNode postProcessNode = fdn.getArgPostProcess(); - if (postProcessNode == null) { - // arguments to this function are not to be reference counted - mask = -1; - return; - } - // this is needed for when FunctionDefinitionNode is split by the Truffle runtime - postProcessNode = postProcessNode.getActualNode(); - if (index >= Math.min(postProcessNode.getLength(), MAX_COUNTED_ARGS)) { - mask = -1; - return; + if (mask != -1) { + writeArgNode.execute(frame, shareable); } - mask = 1 << index; - int transArgsBitSet = postProcessNode.transArgsBitSet; - postProcessNode.transArgsBitSet = transArgsBitSet | mask; - writeArgNode = insert(WriteLocalFrameVariableNode.createForRefCount(Integer.valueOf(mask))); - } - if (mask != -1) { - writeArgNode.execute(frame, shareable); } } } @@ -135,8 +137,7 @@ public abstract class ArgumentStatePush extends Node { // this is expected to be used in rare cases where no RNode is easily available if (o instanceof RShareable) { RShareable shareable = (RShareable) o; - // it's never decremented so no point in incrementing past shared state - if (!shareable.isShared()) { + if (!shareable.isSharedPermanent()) { shareable.incRefCount(); } } 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 a28e67e0ffcdb8844f13e333bb4defb6d1bc4c9d..6cf27926a04a0aac6d089a00f9214985248a7642 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 @@ -16,26 +16,25 @@ import java.util.function.Supplier; 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.VirtualFrame; -import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.ExplodeLoop; -import com.oracle.truffle.api.nodes.IndirectCallNode; 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.nodes.RRootNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.ArgumentMatcher.MatchPermutation; -import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; +import com.oracle.truffle.r.nodes.function.call.CallRFunctionCachedNode; +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.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; -import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.REmpty; import com.oracle.truffle.r.runtime.data.RFunction; @@ -50,7 +49,6 @@ public abstract class CallMatcherNode extends RBaseNode { protected final boolean argsAreEvaluated; @Child private PromiseHelperNode promiseHelper; - @Child private RArgumentsNode argsNode = RArgumentsNode.create(); protected final ConditionProfile missingArgProfile = ConditionProfile.createBinaryProfile(); protected final ConditionProfile emptyArgProfile = ConditionProfile.createBinaryProfile(); @@ -128,10 +126,6 @@ public abstract class CallMatcherNode extends RBaseNode { return new CallMatcherCachedNode(suppliedSignature, varArgSignatures, function, preparePermutation, permutation, forNextMethod, argsAreEvaluated, next); } - protected Object[] prepareArguments(Object[] reorderedArgs, ArgumentsSignature reorderedSignature, RFunction function, DispatchArgs dispatchArgs, RCaller caller) { - return argsNode.execute(function, caller, null, reorderedArgs, reorderedSignature, dispatchArgs); - } - protected final void evaluatePromises(VirtualFrame frame, RFunction function, Object[] args, int varArgIndex) { if (function.isBuiltin()) { if (!argsAreEvaluated) { @@ -185,7 +179,7 @@ public abstract class CallMatcherNode extends RBaseNode { CallMatcherCachedNode cachedNode = replace(specialize(suppliedSignature, suppliedArguments, function, this)); // for splitting if necessary if (cachedNode.call != null && RCallNode.needsSplitting(function.getTarget())) { - cachedNode.call.cloneCallTarget(); + cachedNode.call.getCallNode().cloneCallTarget(); } return cachedNode.execute(frame, suppliedSignature, suppliedArguments, function, functionName, dispatchArgs); } @@ -200,11 +194,10 @@ public abstract class CallMatcherNode extends RBaseNode { private static final class CallMatcherCachedNode extends CallMatcherNode { @Child private CallMatcherNode next; - - @Child private DirectCallNode call; - + @Child private CallRFunctionNode call; @Child private RBuiltinNode builtin; @Children private final CastNode[] builtinArgumentCasts; + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); private final RBuiltinDescriptor builtinDescriptor; private final ArgumentsSignature cachedSuppliedSignature; @@ -233,7 +226,7 @@ public abstract class CallMatcherNode extends RBaseNode { this.builtin = RBuiltinNode.inline(builtinDescriptor, null); this.builtinArgumentCasts = builtin.getCasts(); } else { - this.call = Truffle.getRuntime().createDirectCallNode(function.getTarget()); + this.call = CallRFunctionNode.create(function.getTarget()); this.builtinArgumentCasts = null; this.builtinDescriptor = null; } @@ -259,12 +252,15 @@ public abstract class CallMatcherNode extends RBaseNode { String genFunctionName = functionName == null ? function.getName() : functionName; Supplier<RSyntaxNode> argsSupplier = RCallerHelper.createFromArguments(genFunctionName, preparePermutation, suppliedArguments, suppliedSignature); RCaller caller = genFunctionName == null ? RCaller.createInvalid(frame, parent) : RCaller.create(frame, parent, argsSupplier); - Object[] arguments = prepareArguments(reorderedArgs, matchedArgs.getSignature(), cachedFunction, dispatchArgs, caller); - return call.call(frame, arguments); + try { + return call.execute(frame, cachedFunction, caller, null, reorderedArgs, matchedArgs.getSignature(), cachedFunction.getEnclosingFrame(), dispatchArgs); + } finally { + visibility.executeAfterCall(frame, caller); + } } else { applyCasts(reorderedArgs); - Object result = builtin.execute(frame, reorderedArgs); - RContext.getInstance().setVisible(builtinDescriptor.getVisibility()); + Object result = builtin.executeBuiltin(frame, reorderedArgs); + visibility.execute(frame, builtinDescriptor.getVisibility()); return result; } } else { @@ -334,7 +330,8 @@ public abstract class CallMatcherNode extends RBaseNode { super(forNextMethod, argsAreEvaluated); } - @Child private IndirectCallNode call = Truffle.getRuntime().createIndirectCallNode(); + @Child private CallRFunctionCachedNode call = CallRFunctionCachedNodeGen.create(0); + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); @Override public Object execute(VirtualFrame frame, ArgumentsSignature suppliedSignature, Object[] suppliedArguments, RFunction function, String functionName, DispatchArgs dispatchArgs) { @@ -346,8 +343,11 @@ public abstract class CallMatcherNode extends RBaseNode { RCaller caller = genFunctionName == null ? RCaller.createInvalid(frame, parent) : RCaller.create(frame, RCallerHelper.createFromArguments(genFunctionName, new RArgsValuesAndNames(reorderedArgs.getArguments(), ArgumentsSignature.empty(reorderedArgs.getLength())))); - Object[] arguments = prepareArguments(reorderedArgs.getArguments(), reorderedArgs.getSignature(), function, dispatchArgs, caller); - return call.call(frame, function.getTarget(), arguments); + try { + return call.execute(frame, function, caller, null, reorderedArgs.getArguments(), reorderedArgs.getSignature(), function.getEnclosingFrame(), dispatchArgs); + } finally { + visibility.executeAfterCall(frame, caller); + } } @Override 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 7fe3e749de501ad8ed7e44ee8299225157f7a38b..a38cea8f3dd5a5708088eea885f8b69d797d6bf2 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 @@ -115,14 +115,14 @@ public abstract class ClassHierarchyNode extends UnaryNode { @Specialization protected RStringVector getClassHrAttributable(RAttributable arg, // - @Cached("createBinaryProfile()") ConditionProfile attrStoraeProfile, // + @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile, // @Cached("createClassProfile()") ValueProfile argProfile) { RAttributes attributes; RAttributable profiledArg; - if (attrStoraeProfile.profile(arg instanceof RAttributeStorage)) { + if (attrStorageProfile.profile(arg instanceof RAttributeStorage)) { + // Note: the seemingly unnecessary cast is here to ensure the method can be inlined attributes = ((RAttributeStorage) arg).getAttributes(); - profiledArg = arg; } else { profiledArg = argProfile.profile(arg); attributes = profiledArg.getAttributes(); 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 260ee359b51c6c32724245f659bf10cf8ca94ada..d78c49331b1e5e2f89f4e1376d71b45735c030e1 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 @@ -47,9 +47,10 @@ import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinFactory; import com.oracle.truffle.r.nodes.control.BreakException; import com.oracle.truffle.r.nodes.control.NextException; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.JumpToTopLevelException; import com.oracle.truffle.r.runtime.ExitException; +import com.oracle.truffle.r.runtime.JumpToTopLevelException; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RArguments.DispatchArgs; import com.oracle.truffle.r.runtime.RArguments.S3Args; @@ -58,14 +59,11 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RErrorHandling; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RSerialize; import com.oracle.truffle.r.runtime.RType; 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.env.REnvironment; 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; @@ -116,6 +114,8 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo @Child private FrameSlotNode dotTargetSlot; @Child private FrameSlotNode dotMethodsSlot; + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); + @Child private PostProcessArgumentsNode argPostProcess; private final boolean needsSplitting; @@ -287,6 +287,7 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo * has no exit handlers (by fiat), so any exceptions from onExits handlers will be * caught above. */ + visibility.executeEndOfFunction(frame); if (argPostProcess != null) { resetArgs.enter(); argPostProcess.execute(frame); @@ -299,18 +300,16 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo onExitExpressionCache = insert(InlineCacheNode.createExpression(3)); } ArrayList<Object> current = getCurrentOnExitList(frame, onExitSlot.executeFrameSlot(frame)); - // Preserve the visibility state as may be changed by the on.exit - boolean isVisible = RContext.getInstance().isVisible(); - try { - for (Object expr : current) { - if (!(expr instanceof RNode)) { - RInternalError.shouldNotReachHere("unexpected type for on.exit entry"); - } - RNode node = (RNode) expr; - onExitExpressionCache.execute(frame, node); + /* + * 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"); } - } finally { - RContext.getInstance().setVisible(isVisible); + RNode node = (RNode) expr; + onExitExpressionCache.execute(frame, node); } } } @@ -388,60 +387,6 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo return getName(); } - /** - * Serialize a function. On entry {@code state} has an active pairlist, whose {@code tag} is the - * enclosing {@link REnvironment}. The {@code car} must be set to the pairlist representing the - * formal arguments (or {@link RNull} if none) and the {@code cdr} to the pairlist representing - * the body. Each formal argument is represented as a pairlist: - * <ul> - * <li>{@code tag}: RSymbol(name)</li> - * <li>{@code car}: Missing or default value</li> - * <li>{@code cdr}: if last formal then RNull else pairlist for next argument. - * </ul> - * N.B. The body is never empty as the syntax "{}" has a value, however if the body is a simple - * expression, e.g. {@code function(x) x}, the body is not represented as a pairlist, just a - * SYMSXP, which is handled transparently in {@code RSerialize.State.closePairList()}. - * - */ - @Override - public void serializeImpl(RSerialize.State state) { - serializeFormals(state); - serializeBody(state); - } - - /** - * Also called by {@link FunctionExpressionNode}. - */ - public void serializeBody(RSerialize.State state) { - state.openPairList(); - body.serialize(state); - state.setCdr(state.closePairList()); - } - - /** - * Also called by {@link FunctionExpressionNode}. - */ - public void serializeFormals(RSerialize.State state) { - FormalArguments formals = getFormalArguments(); - int formalsLength = formals.getSignature().getLength(); - if (formalsLength > 0) { - for (int i = 0; i < formalsLength; i++) { - RNode defaultArg = formals.getDefaultArgument(i); - state.openPairList(); - state.setTagAsSymbol(formals.getSignature().getName(i)); - if (defaultArg != null) { - state.serializeNodeSetCar(defaultArg); - } else { - state.setCarMissing(); - } - } - state.linkPairList(formalsLength); - state.setCar(state.closePairList()); - } else { - state.setCar(RNull.instance); - } - } - public void setName(String name) { this.name = name; } 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 1c6ad1065678d682ac7c361b83d37ae25c33be5a..472020d8bcd90a4d6b26db4d23e37fa2ec1496ae 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 @@ -34,13 +34,10 @@ import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseDeoptimizeFr import com.oracle.truffle.r.nodes.function.opt.EagerEvalHelper; import com.oracle.truffle.r.nodes.instrumentation.RInstrumentation; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RSerialize; import com.oracle.truffle.r.runtime.builtins.FastPathFactory; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; -import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction; @@ -96,27 +93,6 @@ public final class FunctionExpressionNode extends RSourceSectionNode implements return callTarget; } - @Override - public void serializeImpl(RSerialize.State state) { - state.setAsBuiltin("function"); - state.openPairList(SEXPTYPE.LISTSXP); - FunctionDefinitionNode fdn = (FunctionDefinitionNode) callTarget.getRootNode(); - /* - * Cannot just serialize fdn, as this needs to generate slightly different output. In - * particular the body is always a LISTSXP and never shortened. - */ - fdn.serializeFormals(state); - state.openPairList(SEXPTYPE.LISTSXP); - fdn.serializeBody(state); - state.switchCdrToCar(); - state.openPairList(SEXPTYPE.LISTSXP); - state.setCar(RNull.instance); - state.setCdr(RNull.instance); - state.setCdr(state.closePairList()); - state.setCdr(state.closePairList()); - state.setCdr(state.closePairList()); - } - @Override public RSyntaxElement[] getSyntaxArgumentDefaults() { return RASTUtils.asSyntaxNodes(((FunctionDefinitionNode) callTarget.getRootNode()).getFormalArguments().getArguments()); 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 5388af445b1d40ace1bf4d33e241a50cbcdc0a50..f1985a8ee73a826c69650208581b73f3270f3377 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 @@ -45,7 +45,6 @@ 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.RInternalError; -import com.oracle.truffle.r.runtime.RSerialize.State; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RMissing; @@ -313,11 +312,6 @@ public abstract class PromiseNode extends RNode { return index; } - @Override - public void serializeImpl(State state) { - throw RInternalError.unimplemented(); - } - @Override public void setSourceSection(SourceSection sourceSection) { throw RInternalError.shouldNotReachHere(); @@ -333,6 +327,7 @@ public abstract class PromiseNode extends RNode { } @Override + @TruffleBoundary public String getIdentifier() { int num = index + 1; return (num < 10 ? ".." : ".") + num; 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 639dc42f661459026a4129b0636bd15454e7c215..de186c6978388c344d79f020d5073c109c1e6028 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 @@ -30,24 +30,20 @@ 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.RootCallTarget; -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.NodeChild; import com.oracle.truffle.api.dsl.Specialization; -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.ForeignAccess; import com.oracle.truffle.api.interop.Message; import com.oracle.truffle.api.interop.TruffleObject; -import com.oracle.truffle.api.nodes.DirectCallNode; 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.NodeUtil; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.api.profiles.BranchProfile; @@ -67,28 +63,29 @@ import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperN import com.oracle.truffle.r.nodes.function.RCallNodeGen.FunctionDispatchNodeGen; import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.NoGenericMethodException; import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.Result; +import com.oracle.truffle.r.nodes.function.call.CallRFunctionNode; 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; import com.oracle.truffle.r.runtime.RArguments.S3Args; import com.oracle.truffle.r.runtime.RArguments.S3DefaultArguments; -import com.oracle.truffle.r.runtime.builtins.FastPathFactory; -import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; -import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.RDispatch; 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.RSerialize; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.RVisibility; import com.oracle.truffle.r.runtime.SubstituteVirtualFrame; -import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.builtins.FastPathFactory; +import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; +import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.REmpty; @@ -98,12 +95,10 @@ 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.gnur.SEXPTYPE; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RFastPathNode; 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.RSyntaxLookup; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @@ -295,14 +290,15 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } @Specialization(limit = "5", guards = {"isSpecialDispatch(function)", "cachedBuiltin == function.getRBuiltin()"}) - public Object callSpecial(VirtualFrame frame, @SuppressWarnings("unused") RFunction function, // - @Cached("function.getRBuiltin()") RBuiltinDescriptor cachedBuiltin, // - @Cached("createSpecial(cachedBuiltin)") RBuiltinNode call) { + public Object callSpecial(VirtualFrame frame, @SuppressWarnings("unused") RFunction function, + @Cached("function.getRBuiltin()") RBuiltinDescriptor cachedBuiltin, + @Cached("createSpecial(cachedBuiltin)") RBuiltinNode call, + @Cached("create()") SetVisibilityNode visibility) { if (explicitArgs != null) { CompilerDirectives.transferToInterpreter(); throw RError.error(this, RError.Message.INVALID_USE, cachedBuiltin.getName()); } - RContext.getInstance().setVisible(cachedBuiltin.getVisibility()); + visibility.execute(frame, cachedBuiltin.getVisibility()); return call.execute(frame); } @@ -312,7 +308,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } protected RNode createDispatchArgument(int index) { - return new ForcePromiseNode(NodeUtil.cloneNode(arguments[index].asRNode())); + return new ForcePromiseNode(RASTUtils.cloneNode(arguments[index].asRNode())); } /** @@ -339,7 +335,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS @Cached("createBinaryProfile()") ConditionProfile resultIsBuiltinProfile) { RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin()); Object dispatchObject = dispatchArgument.execute(frame); - FrameSlot slot = dispatchTempSlot.initialize(frame, dispatchObject, () -> internalDispatchCall = null); + dispatchTempSlot.initialize(frame, dispatchObject, () -> internalDispatchCall = null); try { RStringVector type = classHierarchyNode.execute(dispatchObject); S3Args s3Args; @@ -362,7 +358,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } return internalDispatchCall.execute(frame, resultFunction, lookupVarArgs(frame), s3Args, null); } finally { - dispatchTempSlot.cleanup(frame, slot); + dispatchTempSlot.cleanup(frame, dispatchObject); } } @@ -569,7 +565,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS return result; } catch (Throwable e) { errorProfile.enter(); - throw RError.error(this, RError.Message.GENERIC, "Foreign function failed: " + e.getMessage() != null ? e.getMessage() : e.toString()); + throw RError.interopError(RError.findParentRBase(this), e, function); } } } @@ -615,81 +611,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS return CallArgumentsNode.create(modeChange, modeChangeAppliesToAll, args, signature, varArgIndexes); } - @Override - public void serializeImpl(RSerialize.State state) { - state.setAsLangType(); - state.serializeNodeSetCar(getFunctionNode()); - if (isColon(getFunctionNode())) { - // special case, have to translate Identifier names to Symbols - RSyntaxNode arg0 = arguments[0]; - RSyntaxNode arg1 = arguments[1]; - state.openPairList(); - if (arg0 instanceof ReadVariableNode) { - state.setCarAsSymbol(((ReadVariableNode) arg0).getIdentifier()); - } else { - state.setCar(((ConstantNode) arg0).getValue()); - } - state.openPairList(); - if (arg1 instanceof ReadVariableNode) { - state.setCarAsSymbol(((ReadVariableNode) arg1).getIdentifier()); - } else { - state.setCar(((ConstantNode) arg1).getValue()); - } - state.linkPairList(2); - state.setCdr(state.closePairList()); - } else { - RSyntaxNode f = getFunctionNode().asRSyntaxNode(); - boolean infixFieldAccess = false; - if (f instanceof RSyntaxLookup) { - RSyntaxLookup lookup = (RSyntaxLookup) f; - infixFieldAccess = "$".equals(lookup.getIdentifier()) || "@".equals(lookup.getIdentifier()); - } - serializeArguments(state, arguments, signature, infixFieldAccess); - } - } - - static void serializeArguments(RSerialize.State state, RSyntaxNode[] arguments, ArgumentsSignature signature, boolean infixFieldAccess) { - state.openPairList(SEXPTYPE.LISTSXP); - if (arguments.length == 0) { - state.setNull(); - } else { - for (int i = 0; i < arguments.length; i++) { - RSyntaxNode argument = arguments[i]; - String name = signature.getName(i); - if (name != null) { - state.setTagAsSymbol(name); - } - if (argument == null) { - state.setCarMissing(); - } else { - if (infixFieldAccess && i == 1 && argument instanceof RSyntaxConstant) { - RSyntaxConstant c = (RSyntaxConstant) argument; - String identifier = RRuntime.asStringLengthOne(c.getValue()); - assert identifier != null; - state.setCarAsSymbol(identifier); - } else { - state.serializeNodeSetCar(argument); - } - } - if (i != arguments.length - 1) { - state.openPairList(); - } - - } - state.linkPairList(arguments.length); - } - state.setCdr(state.closePairList()); - } - - private static boolean isColon(RNode node) { - if (node instanceof ReadVariableNode) { - ReadVariableNode rvn = (ReadVariableNode) node; - String name = rvn.getIdentifier(); - return name.equals("::") || name.equals(":::"); - } - return false; - } - /** * Creates a call to a resolved {@link RBuiltinKind#INTERNAL} that will be used to replace the * original call. @@ -839,7 +760,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS FormalArguments formals = root.getFormalArguments(); if (root instanceof RBuiltinRootNode) { RBuiltinRootNode builtinRoot = (RBuiltinRootNode) root; - return new BuiltinCallNode(RBuiltinNode.inline(builtinRoot.getBuiltin(), null), builtinRoot.getBuiltin(), formals, originalCall); + return new BuiltinCallNode(RBuiltinNode.inline(builtinRoot.getBuiltin(), null), builtinRoot.getBuiltin(), formals, originalCall, explicitArgs); } else { return new DispatchedCallNode(cachedTarget, originalCall); } @@ -928,35 +849,54 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS private static final class BuiltinCallNode extends LeafCallNode { @Child private RBuiltinNode builtin; - @Child private PromiseCheckHelperNode promiseHelper; + @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 + @CompilationFinal private final boolean[] argEmptySeen; + @CompilationFinal private final boolean[] varArgSeen; + @CompilationFinal private final boolean[] nonWrapSeen; + @CompilationFinal private final boolean[] wrapSeen; - private final BranchProfile emptyProfile = BranchProfile.create(); - private final BranchProfile varArgsProfile = BranchProfile.create(); - private final ConditionProfile wrapProfile = ConditionProfile.createBinaryProfile(); private final FormalArguments formals; private final RBuiltinDescriptor builtinDescriptor; + private final boolean explicitArgs; - BuiltinCallNode(RBuiltinNode builtin, RBuiltinDescriptor builtinDescriptor, FormalArguments formalArguments, RCallNode originalCall) { + BuiltinCallNode(RBuiltinNode builtin, RBuiltinDescriptor builtinDescriptor, FormalArguments formalArguments, RCallNode originalCall, boolean explicitArgs) { super(originalCall); 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()]; + varArgSeen = new boolean[formals.getLength()]; + nonWrapSeen = new boolean[formals.getLength()]; + wrapSeen = new boolean[formals.getLength()]; } @ExplodeLoop public Object[] castArguments(VirtualFrame frame, Object[] args) { int argCount = formals.getLength(); + int varArgIndex = formals.getSignature().getVarArgIndex(); Object[] result = new Object[argCount]; for (int i = 0; i < argCount; i++) { Object arg = args[i]; - if (arg == REmpty.instance) { - emptyProfile.enter(); + if (explicitArgs && arg == REmpty.instance) { + if (!argEmptySeen[i]) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + argEmptySeen[i] = true; + } arg = formals.getInternalDefaultArgumentAt(i); } - if (arg instanceof RArgsValuesAndNames) { - varArgsProfile.enter(); + if (varArgIndex == i && arg instanceof RArgsValuesAndNames) { + if (!varArgSeen[i]) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + varArgSeen[i] = true; + } RArgsValuesAndNames varArgs = (RArgsValuesAndNames) arg; if (builtinDescriptor.evaluatesArg(i)) { forcePromises(frame, varArgs); @@ -966,12 +906,11 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } else { if (builtinDescriptor.evaluatesArg(i)) { if (arg instanceof RPromise) { - if (promiseHelper == null) { + if (promiseHelpers[i] == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - promiseHelper = insert(new PromiseCheckHelperNode()); + promiseHelpers[i] = insert(new PromiseHelperNode()); } - arg = promiseHelper.checkEvaluate(frame, arg); - + arg = promiseHelpers[i].evaluate(frame, (RPromise) arg); } if (i < casts.length && casts[i] != null) { assert builtinDescriptor.evaluatesArg(i); @@ -979,7 +918,16 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } } else { assert casts.length <= i || casts[i] == null : "no casts allowed on non-evaluated arguments"; - if (wrapProfile.profile(!(arg instanceof RPromise || arg instanceof RMissing))) { + if (arg instanceof RPromise || arg instanceof RMissing) { + if (!nonWrapSeen[i]) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + nonWrapSeen[i] = true; + } + } else { + if (!wrapSeen[i]) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + wrapSeen[i] = true; + } arg = createPromise(arg); } } @@ -989,14 +937,34 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS return result; } + private final VectorLengthProfile varArgProfile = VectorLengthProfile.create(); + private void forcePromises(VirtualFrame frame, RArgsValuesAndNames varArgs) { + if (varArgsPromiseHelper == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + varArgsPromiseHelper = insert(new PromiseCheckHelperNode()); + } + varArgProfile.profile(varArgs.getLength()); + int cachedLength = varArgProfile.getCachedLength(); + if (cachedLength >= 0) { + forcePromisesUnrolled(frame, varArgs, cachedLength); + } else { + forcePromisesDynamic(frame, varArgs); + } + } + + @ExplodeLoop + private void forcePromisesUnrolled(VirtualFrame frame, RArgsValuesAndNames varArgs, int length) { + Object[] array = varArgs.getArguments(); + for (int i = 0; i < length; i++) { + array[i] = varArgsPromiseHelper.checkEvaluate(frame, array[i]); + } + } + + private void forcePromisesDynamic(VirtualFrame frame, RArgsValuesAndNames varArgs) { Object[] array = varArgs.getArguments(); for (int i = 0; i < array.length; i++) { - if (promiseHelper == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - promiseHelper = insert(new PromiseCheckHelperNode()); - } - array[i] = promiseHelper.checkEvaluate(frame, array[i]); + array[i] = varArgsPromiseHelper.checkEvaluate(frame, array[i]); } } @@ -1017,16 +985,17 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS @Override public Object execute(VirtualFrame frame, RFunction currentFunction, RArgsValuesAndNames orderedArguments, S3Args s3Args) { - Object result = builtin.execute(frame, castArguments(frame, orderedArguments.getArguments())); - RContext.getInstance().setVisible(builtinDescriptor.getVisibility()); + Object result = builtin.executeBuiltin(frame, castArguments(frame, orderedArguments.getArguments())); + visibility.execute(frame, builtinDescriptor.getVisibility()); return result; } } private static final class DispatchedCallNode extends LeafCallNode { - @Child private DirectCallNode call; + @Child private CallRFunctionNode call; @Child private RFastPathNode fastPath; + @Child private SetVisibilityNode visibility; private final RootCallTarget cachedTarget; private final FastPathFactory fastPathFactory; @@ -1039,6 +1008,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS this.fastPathFactory = root.getFastPath(); this.fastPath = fastPathFactory == null ? null : fastPathFactory.create(); this.fastPathVisibility = fastPathFactory == null ? null : fastPathFactory.getVisibility(); + this.visibility = fastPathFactory == null ? null : SetVisibilityNode.create(); originalCall.needsCallerFrame |= root.containsDispatch(); } @@ -1047,25 +1017,26 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS if (fastPath != null) { Object result = fastPath.execute(frame, orderedArguments.getArguments()); if (result != null) { - RContext.getInstance().setVisible(this.fastPathVisibility); + assert fastPathVisibility != null; + visibility.execute(frame, fastPathVisibility); return result; } CompilerDirectives.transferToInterpreterAndInvalidate(); fastPath = null; + visibility = null; } if (call == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - call = insert(Truffle.getRuntime().createDirectCallNode(cachedTarget)); + call = insert(CallRFunctionNode.create(cachedTarget)); if (needsSplitting(cachedTarget)) { - call.cloneCallTarget(); + call.getCallNode().cloneCallTarget(); } } MaterializedFrame callerFrame = /* CompilerDirectives.inInterpreter() || */originalCall.needsCallerFrame ? frame.materialize() : null; - Object[] argsObject = RArguments.create(function, originalCall.createCaller(frame, function), callerFrame, orderedArguments.getArguments(), orderedArguments.getSignature(), + return call.execute(frame, function, originalCall.createCaller(frame, function), callerFrame, orderedArguments.getArguments(), orderedArguments.getSignature(), function.getEnclosingFrame(), s3Args); - return call.call(frame, argsObject); } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..8284911e05cf5e38cf6964e9fa02ad842405f00a --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2016, 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.function; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RDeparse; +import com.oracle.truffle.r.runtime.RInternalError; +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.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.RSyntaxLookup; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; + +final class PeekLocalVariableNode extends RNode { + + @Child private LocalReadVariableNode read; + + private final ConditionProfile isPromiseProfile = ConditionProfile.createBinaryProfile(); + + PeekLocalVariableNode(String name) { + this.read = LocalReadVariableNode.create(name, false); + } + + @Override + public Object execute(VirtualFrame frame) { + Object value = read.execute(frame); + if (value == null) { + throw RCallSpecialNode.fullCallNeeded(); + } + if (isPromiseProfile.profile(value instanceof RPromise)) { + RPromise promise = (RPromise) value; + if (!promise.isEvaluated()) { + throw RCallSpecialNode.fullCallNeeded(); + } + return promise.getValue(); + } + return value; + } +} + +public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode, RSyntaxCall { + + // currently cannot be RSourceSectionNode because of TruffleDSL restrictions + + @CompilationFinal private SourceSection sourceSectionR; + + @Override + public void setSourceSection(SourceSection sourceSection) { + assert sourceSection != null; + this.sourceSectionR = sourceSection; + } + + @Override + public SourceSection getSourceSection() { + return sourceSectionR; + } + + public static RuntimeException fullCallNeeded() { + CompilerDirectives.transferToInterpreterAndInvalidate(); + throw RSpecialFactory.FULL_CALL_NEEDED; + } + + @Child private ForcePromiseNode functionNode; + @Child private RNode special; + + private final RSyntaxNode[] arguments; + private final ArgumentsSignature signature; + private final RFunction expectedFunction; + + private RCallSpecialNode(SourceSection sourceSection, RNode functionNode, RFunction expectedFunction, RSyntaxNode[] arguments, ArgumentsSignature signature, RNode special) { + this.sourceSectionR = sourceSection; + this.expectedFunction = expectedFunction; + this.special = special; + this.functionNode = new ForcePromiseNode(functionNode); + this.arguments = arguments; + this.signature = signature; + } + + public static RSyntaxNode createCall(SourceSection sourceSection, RNode functionNode, ArgumentsSignature signature, RSyntaxNode[] arguments) { + RCallSpecialNode special = tryCreate(sourceSection, functionNode, signature, arguments); + if (special != null) { + if (sourceSection == RSyntaxNode.EAGER_DEPARSE) { + RDeparse.ensureSourceSection(special); + } + return special; + } else { + return RCallNode.createCall(sourceSection, functionNode, signature, arguments); + } + } + + private static RCallSpecialNode tryCreate(SourceSection sourceSection, RNode functionNode, ArgumentsSignature signature, RSyntaxNode[] arguments) { + RSyntaxNode syntaxFunction = functionNode.asRSyntaxNode(); + if (!(syntaxFunction instanceof RSyntaxLookup)) { + // LHS is not a simple lookup -> bail out + return null; + } + for (RSyntaxNode argument : arguments) { + if (!(argument instanceof RSyntaxLookup || argument instanceof RSyntaxConstant)) { + // argument is not a simple lookup or constant value -> bail out + return null; + } + } + String name = ((RSyntaxLookup) syntaxFunction).getIdentifier(); + RBuiltinDescriptor builtinDescriptor = RContext.lookupBuiltinDescriptor(name); + if (builtinDescriptor == null) { + // no builtint -> bail out + return null; + } + RSpecialFactory specialCall = builtinDescriptor.getSpecialCall(); + if (specialCall == null) { + // no special call definition -> bail out + return null; + } + RNode[] localArguments = new RNode[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + if (arguments[i] instanceof RSyntaxLookup) { + localArguments[i] = new PeekLocalVariableNode(((RSyntaxLookup) arguments[i]).getIdentifier()); + } else { + assert arguments[i] instanceof RSyntaxConstant; + localArguments[i] = RContext.getASTBuilder().process(arguments[i]).asRNode(); + } + } + RNode special = specialCall.create(signature, localArguments); + if (special == null) { + // the factory refused to create a special call -> bail out + return null; + } + RFunction expectedFunction = RContext.lookupBuiltin(name); + RInternalError.guarantee(expectedFunction != null); + + return new RCallSpecialNode(sourceSection, functionNode, expectedFunction, arguments, signature, special); + } + + @Override + public Object execute(VirtualFrame frame, Object function) { + try { + if (function != expectedFunction) { + // the actual function differs from the expected function + throw RCallSpecialNode.fullCallNeeded(); + } + return special.execute(frame); + } catch (RSpecialFactory.FullCallNeededException e) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + RCallNode call = RCallNode.createCall(sourceSectionR, functionNode == null ? null : functionNode.getValueNode(), signature, arguments); + return replace(call).execute(frame, function); + } + } + + @Override + public Object execute(VirtualFrame frame) { + return execute(frame, functionNode.execute(frame)); + } + + @Override + public RSyntaxElement getSyntaxLHS() { + ForcePromiseNode func = functionNode; + return func == null || func.getValueNode() == null ? RSyntaxLookup.createDummyLookup(RSyntaxNode.LAZY_DEPARSE, "FUN", true) : func.getValueNode().asRSyntaxNode(); + } + + @Override + public ArgumentsSignature getSyntaxSignature() { + return signature == null ? ArgumentsSignature.empty(1) : signature; + } + + @Override + public RSyntaxElement[] getSyntaxArguments() { + return arguments == null ? new RSyntaxElement[]{RSyntaxLookup.createDummyLookup(RSyntaxNode.LAZY_DEPARSE, "...", false)} : arguments; + } +} 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 56c0751202f6e38fef94f115bb4dcf895ce01efc..cab3f3c4da90b28fb840338a03006ebcd7bb9b31 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 @@ -23,50 +23,53 @@ 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.Node; -import com.oracle.truffle.r.nodes.access.FrameSlotNode; import com.oracle.truffle.r.runtime.RInternalError; 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()}; - @Child private FrameSlotNode tempSlot; + @CompilationFinal private FrameSlot tempSlot; private int tempIdentifier; private Object identifier; - public FrameSlot initialize(VirtualFrame frame, Object value, Runnable invalidate) { + public void initialize(VirtualFrame frame, Object value, Runnable invalidate) { if (tempSlot == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - tempSlot = insert(FrameSlotNode.createInitialized(frame.getFrameDescriptor(), identifier = defaultTempIdentifiers[0], true)); + tempSlot = frame.getFrameDescriptor().findOrAddFrameSlot(identifier = defaultTempIdentifiers[0], FrameSlotKind.Object); invalidate.run(); } - FrameSlot slot = tempSlot.executeFrameSlot(frame); try { - if (frame.isObject(slot) && frame.getObject(slot) != null) { + if (frame.getObject(tempSlot) != null) { CompilerDirectives.transferToInterpreterAndInvalidate(); // keep the complete loop in the slow path do { tempIdentifier++; identifier = tempIdentifier < defaultTempIdentifiers.length ? defaultTempIdentifiers[tempIdentifier] : new Object(); - tempSlot.replace(FrameSlotNode.createInitialized(frame.getFrameDescriptor(), identifier, true)); + tempSlot = frame.getFrameDescriptor().findOrAddFrameSlot(identifier, FrameSlotKind.Object); invalidate.run(); - slot = tempSlot.executeFrameSlot(frame); - } while (frame.isObject(slot) && frame.getObject(slot) != null); + } while (frame.getObject(tempSlot) != null); } } catch (FrameSlotTypeException e) { + CompilerDirectives.transferToInterpreter(); throw RInternalError.shouldNotReachHere(); } - frame.setObject(slot, value); - return slot; + frame.setObject(tempSlot, value); } - @SuppressWarnings("static-method") - public void cleanup(VirtualFrame frame, FrameSlot slot) { - frame.setObject(slot, null); + public void cleanup(VirtualFrame frame, Object object) { + try { + assert frame.getObject(tempSlot) == object; + } catch (FrameSlotTypeException e) { + throw RInternalError.shouldNotReachHere(); + } + frame.setObject(tempSlot, null); } public Object getIdentifier() { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodInternalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodInternalNode.java index da4f5715c1e4add5da9d72ea7b84b4e1766f5275..284b6b0c0825045733416846ed73b1ab1641f761 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodInternalNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodInternalNode.java @@ -17,7 +17,6 @@ import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RArguments.S3Args; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.nodes.RNode; @@ -39,7 +38,6 @@ public final class UseMethodInternalNode extends RNode { } public Object execute(VirtualFrame frame, RStringVector type, Object[] arguments) { - RContext.getInstance().setVisible(true); Result lookupResult = lookup.execute(frame, generic, type, null, frame.materialize(), null); if (wrap) { assert arguments != 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 ea78fd31ab168ccb3dd5c1bde48c717af525b335..722e6566d56123ae845ef36608b91fc83c4910b8 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 @@ -73,7 +73,7 @@ public abstract class WrapArgumentBaseNode extends RNode { Object result = argumentValueProfile.profile(initialResult); if (result instanceof RVector) { everSeenVector.enter(); - return (RVector) result; + return (RVector<?>) result; } else if (result instanceof RLanguage) { everSeenLanguage.enter(); return (RLanguage) result; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionCachedNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionCachedNode.java new file mode 100644 index 0000000000000000000000000000000000000000..bb8e9eb11a7da751329c6c5205821c8ad125a85c --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionCachedNode.java @@ -0,0 +1,94 @@ +/* + * 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.nodes.function.call; + +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.dsl.Cached; +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.api.nodes.DirectCallNode; +import com.oracle.truffle.api.nodes.IndirectCallNode; +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.nodes.function.visibility.SetVisibilityNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RArguments.DispatchArgs; +import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.data.RFunction; + +@NodeInfo(cost = NodeCost.NONE) +public abstract class CallRFunctionCachedNode extends Node { + + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); + + protected final int cacheLimit; + + protected CallRFunctionCachedNode(int cacheLimit) { + this.cacheLimit = cacheLimit; + } + + public final Object execute(VirtualFrame frame, RFunction function, RCaller call, MaterializedFrame callerFrame, Object[] evaluatedArgs, DispatchArgs dispatchArgs) { + Object[] callArgs = RArguments.create(function, call, callerFrame, evaluatedArgs, dispatchArgs); + return execute(frame, function.getTarget(), callArgs, call); + } + + public final Object execute(VirtualFrame frame, RFunction function, RCaller call, MaterializedFrame callerFrame, Object[] evaluatedArgs, + ArgumentsSignature suppliedSignature, MaterializedFrame enclosingFrame, DispatchArgs dispatchArgs) { + Object[] callArgs = RArguments.create(function, call, callerFrame, evaluatedArgs, suppliedSignature, enclosingFrame, dispatchArgs); + return execute(frame, function.getTarget(), callArgs, call); + } + + protected abstract Object execute(VirtualFrame frame, CallTarget target, Object[] arguments, RCaller caller); + + protected static DirectCallNode createDirectCallNode(CallTarget target) { + return Truffle.getRuntime().createDirectCallNode(target); + } + + @Specialization(guards = "target == callNode.getCallTarget()", limit = "cacheLimit") + protected Object call(VirtualFrame frame, @SuppressWarnings("unused") CallTarget target, Object[] arguments, RCaller caller, + @Cached("createDirectCallNode(target)") DirectCallNode callNode) { + try { + return callNode.call(frame, arguments); + } finally { + visibility.executeAfterCall(frame, caller); + } + } + + protected static IndirectCallNode createIndirectCallNode() { + return Truffle.getRuntime().createIndirectCallNode(); + } + + @Specialization + protected Object call(VirtualFrame frame, CallTarget target, Object[] arguments, RCaller caller, + @Cached("createIndirectCallNode()") IndirectCallNode callNode) { + try { + return callNode.call(frame, target, arguments); + } finally { + visibility.executeAfterCall(frame, caller); + } + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionNode.java new file mode 100644 index 0000000000000000000000000000000000000000..9b6737a530c67631391b3dbc6d24c3a9d67a484b --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionNode.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016, 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.function.call; + +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.DirectCallNode; +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.nodes.function.visibility.SetVisibilityNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RArguments.DispatchArgs; +import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.data.RFunction; + +@NodeInfo(cost = NodeCost.NONE) +public final class CallRFunctionNode extends Node { + + @Child private DirectCallNode callNode; + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); + + private CallRFunctionNode(CallTarget callTarget) { + this.callNode = Truffle.getRuntime().createDirectCallNode(callTarget); + } + + public static CallRFunctionNode create(CallTarget callTarget) { + return new CallRFunctionNode(callTarget); + } + + public Object execute(VirtualFrame frame, RFunction function, RCaller caller, MaterializedFrame callerFrame, Object[] evaluatedArgs, ArgumentsSignature suppliedSignature, + MaterializedFrame enclosingFrame, DispatchArgs dispatchArgs) { + Object[] callArgs = RArguments.create(function, caller, callerFrame, evaluatedArgs, suppliedSignature, enclosingFrame, dispatchArgs); + try { + return callNode.call(frame, callArgs); + } finally { + visibility.executeAfterCall(frame, caller); + } + } + + public DirectCallNode getCallNode() { + return callNode; + } + + public static Object executeSlowpath(RFunction function, RCaller caller, MaterializedFrame callerFrame, Object[] evaluatedArgs, DispatchArgs dispatchArgs) { + Object[] callArgs = RArguments.create(function, caller, callerFrame, evaluatedArgs, dispatchArgs); + try { + return function.getTarget().call(callArgs); + } finally { + SetVisibilityNode.executeAfterCallSlowPath(callerFrame, caller); + } + } +} 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 70aa1febcc3f89bd62a47e8a2adedf89b42c399a..2c16f2947c28624c1d292ec29d591ea2674a714f 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 @@ -30,6 +30,12 @@ import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage; +/** + * 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. + */ public abstract class ReuseNonSharedNode extends Node { public static ReuseNonSharedNode create() { @@ -41,33 +47,22 @@ public abstract class ReuseNonSharedNode extends Node { @Specialization protected RShareable getStorage(RSharingAttributeStorage value, // @Cached("createBinaryProfile()") ConditionProfile isSharedProfile, // - @Cached("createBinaryProfile()") ConditionProfile isTemporaryProfile, // @Cached("createClassProfile()") ValueProfile copyProfile) { if (isSharedProfile.profile(value.isShared())) { RShareable res = copyProfile.profile(value).copy(); assert res.isTemporary(); - res.incRefCount(); return res; } - if (isTemporaryProfile.profile(value.isTemporary())) { - value.incRefCount(); - } return value; } @Specialization(contains = "getStorage") protected static RShareable getRShareable(RShareable value, // - @Cached("createBinaryProfile()") ConditionProfile isSharedProfile, // - @Cached("createBinaryProfile()") ConditionProfile isTemporaryProfile) { + @Cached("createBinaryProfile()") ConditionProfile isSharedProfile) { if (isSharedProfile.profile(value.isShared())) { RShareable res = value.copy(); - assert res.isTemporary(); - res.incRefCount(); return res; } - if (isTemporaryProfile.profile(value.isTemporary())) { - value.incRefCount(); - } 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 new file mode 100644 index 0000000000000000000000000000000000000000..1804aefa97082f9efdc65cc65cf5bf7f0b62a5e2 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ShareObjectNode.java @@ -0,0 +1,59 @@ +/* + * 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.function.opt; + +import com.oracle.truffle.api.dsl.Cached; +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.r.runtime.data.RShareable; + +/** + * Internal node that should be used whenever you need to increment reference count of some object. + * If the object is not instance of {@link RShareable} or if it is shared permanent, then does + * nothing. + */ +public abstract class ShareObjectNode extends Node { + public abstract Object execute(Object obj); + + public static ShareObjectNode create() { + return ShareObjectNodeGen.create(); + } + + @Specialization + protected Object doShareable(RShareable obj, @Cached("createBinaryProfile()") ConditionProfile sharedPermanent) { + if (sharedPermanent.profile(!obj.isSharedPermanent())) { + obj.incRefCount(); + } + return obj; + } + + @Specialization(guards = "!isRShareable(obj)") + protected Object doNonShareable(Object obj) { + return obj; + } + + protected static boolean isRShareable(Object value) { + return value instanceof RShareable; + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/RArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/RArgumentsNode.java deleted file mode 100644 index 244c55359e7f6bc046ae731e45ff3fea0e17a9ee..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/RArgumentsNode.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2015, 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.function.signature; - -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.frame.MaterializedFrame; -import com.oracle.truffle.api.nodes.NodeCost; -import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RArguments; -import com.oracle.truffle.r.runtime.RArguments.DispatchArgs; -import com.oracle.truffle.r.runtime.RCaller; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; - -public abstract class RArgumentsNode extends RBaseNode { - - /* - * This inline cache is not implemented using Truffle DSL because of null values provided for - * certain parameters, on which Truffle DSL cannot specialize. - */ - - public abstract Object[] execute(RFunction function, RCaller caller, MaterializedFrame callerFrame, Object[] evaluatedArgs, ArgumentsSignature signature, DispatchArgs dispatchArgs); - - public static RArgumentsNode create() { - return new RArgumentsUninitializedNode(); - } - - @Override - public NodeCost getCost() { - return NodeCost.NONE; - } - - private static final class RArgumentsUninitializedNode extends RArgumentsNode { - @Override - public Object[] execute(RFunction function, RCaller caller, MaterializedFrame callerFrame, Object[] evaluatedArgs, ArgumentsSignature signature, DispatchArgs dispatchArgs) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - return replace(new RArgumentsCachedNode(function)).execute(function, caller, callerFrame, evaluatedArgs, signature, dispatchArgs); - } - } - - private static final class RArgumentsCachedNode extends RArgumentsNode { - private final RFunction cachedFunction; - - RArgumentsCachedNode(RFunction cachedFunction) { - this.cachedFunction = cachedFunction; - } - - @Override - public Object[] execute(RFunction function, RCaller caller, MaterializedFrame callerFrame, Object[] evaluatedArgs, ArgumentsSignature signature, DispatchArgs dispatchArgs) { - if (function == cachedFunction) { - return RArguments.create(cachedFunction, caller, callerFrame, evaluatedArgs, cachedFunction.getEnclosingFrame(), dispatchArgs); - } else { - CompilerDirectives.transferToInterpreterAndInvalidate(); - return replace(new RArgumentsGenericNode()).execute(function, caller, callerFrame, evaluatedArgs, signature, dispatchArgs); - } - } - } - - private static final class RArgumentsGenericNode extends RArgumentsNode { - @Override - public Object[] execute(RFunction function, RCaller caller, MaterializedFrame callerFrame, Object[] evaluatedArgs, ArgumentsSignature signature, DispatchArgs dispatchArgs) { - return RArguments.create(function, caller, callerFrame, evaluatedArgs, function.getEnclosingFrame(), dispatchArgs); - } - } -} 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 new file mode 100644 index 0000000000000000000000000000000000000000..51f0af3d130d32144cdc0af61e3783d4a6c7a33c --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/GetVisibilityNode.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016, 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.function.visibility; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +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.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.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.env.frame.RFrameSlot; + +/** + * See {@link RFrameSlot#Visibility}. + */ +@NodeInfo(cost = NodeCost.NONE) +public final class GetVisibilityNode extends Node { + + @CompilationFinal private FrameSlot frameSlot; + private final ConditionProfile isUninitializedProfile = ConditionProfile.createBinaryProfile(); + + private GetVisibilityNode() { + } + + public static GetVisibilityNode create() { + return new GetVisibilityNode(); + } + + public boolean execute(Frame frame) { + if (frameSlot == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + frameSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Object); + } + try { + Object visibility = frame.getObject(frameSlot); + if (isUninitializedProfile.profile(visibility == null)) { + return false; + } else { + return visibility == Boolean.TRUE; + } + } catch (FrameSlotTypeException e) { + throw RInternalError.shouldNotReachHere(e); + } + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..a70e2005bc549aeb8d6fe41c9e3061773e776e29 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016, 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.function.visibility; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +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.nodes.Node; +import com.oracle.truffle.api.nodes.NodeCost; +import com.oracle.truffle.api.nodes.NodeInfo; +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.RFrameSlot; + +/** + * See {@link RFrameSlot#Visibility}. + */ +@NodeInfo(cost = NodeCost.NONE) +public final class SetVisibilityNode extends Node { + + @CompilationFinal private FrameSlot frameSlot; + + private SetVisibilityNode() { + } + + public static SetVisibilityNode create() { + return new SetVisibilityNode(); + } + + private void ensureFrameSlot(Frame frame) { + if (frameSlot == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + frameSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Object); + } + } + + public void execute(Frame frame, boolean value) { + ensureFrameSlot(frame); + frame.setObject(frameSlot, value); + } + + public void execute(VirtualFrame frame, RVisibility visibility) { + if (visibility == RVisibility.ON) { + execute(frame, true); + } else if (visibility == RVisibility.OFF) { + execute(frame, false); + } + } + + /** + * Needs to be called after each call site, so that the visibility is transferred from the + * {@link RCaller} to the current frame. + */ + public void executeAfterCall(VirtualFrame frame, RCaller caller) { + ensureFrameSlot(frame); + frame.setObject(frameSlot, caller.getVisibility()); + } + + /** + * Needs to be called at the end of each function, so that the visibility is transferred from + * the current frame into the {@link RCaller}. + */ + public void executeEndOfFunction(VirtualFrame frame) { + ensureFrameSlot(frame); + try { + Object visibility = frame.getObject(frameSlot); + if (visibility != null) { + RArguments.getCall(frame).setVisibility(visibility == Boolean.TRUE); + } + } catch (FrameSlotTypeException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + /** + * Slow-path version of {@link #executeAfterCall(VirtualFrame, RCaller)}. + */ + public static void executeAfterCallSlowPath(Frame frame, RCaller caller) { + frame.setObject(frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Object), caller.getVisibility()); + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java index 2c468c42b1bbd4b6c25dfb88ff3952db68b03e5c..85fb3995c0838da54cf667862767ae5576beb39f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java @@ -82,11 +82,11 @@ public final class RFactorNodes { Object attr = attrAccess.execute(factor.getAttributes()); // Convert scalars to vector if necessary - RVector vec; + RVector<?> vec; if (nonScalarLevels.profile(attr instanceof RVector)) { - vec = (RVector) attr; + vec = (RVector<?>) attr; } else if (attr != null) { - vec = (RVector) RRuntime.asAbstractVector(attr); // scalar to vector + vec = (RVector<?>) RRuntime.asAbstractVector(attr); // scalar to vector } else { notVectorBranch.enter(); // N.B: when a factor is lacking the 'levels' attribute, GNU R uses range 1:14331272 @@ -101,7 +101,7 @@ public final class RFactorNodes { } else { if (castString == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - castString = insert(CastStringNodeGen.create(false, false, false, false)); + castString = insert(CastStringNodeGen.create(false, false, false)); } RStringVector slevels = (RStringVector) castString.executeString(vec); return RDataFactory.createStringVector(slevels.getDataWithoutCopying(), RDataFactory.COMPLETE_VECTOR); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RFunctionProfiler.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RFunctionProfiler.java deleted file mode 100644 index d3158a4c3e13a058b87ed179d903eaec0db6c873..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RFunctionProfiler.java +++ /dev/null @@ -1,210 +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.nodes.instrumentation; - -import java.util.Arrays; -import java.util.Map; - -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.r.runtime.RPerfStats; -import com.oracle.truffle.r.runtime.RSource; -import com.oracle.truffle.r.runtime.Utils; -import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.tools.Profiler; -import com.oracle.truffle.tools.Profiler.Counter; -import com.oracle.truffle.tools.Profiler.Counter.TimeKind; - -/** - * Interface to the Truffle {@link Profiler}. - */ -public class RFunctionProfiler { - static { - RPerfStats.register(new PerfHandler()); - } - - static boolean enabled() { - return RPerfStats.enabled(PerfHandler.NAME); - } - - /** - * This is called on startup to support {@link RPerfStats}. - */ - static void installTimers(RContext context) { - if (enabled()) { - enableTiming(context, true, true); - } - } - - private static Profiler getProfiler(RContext context) { - PolyglotEngine vm = context.getVM(); - Profiler profiler = Profiler.find(vm); - return profiler; - } - - private static Profiler getProfiler() { - PolyglotEngine vm = RContext.getInstance().getVM(); - Profiler profiler = Profiler.find(vm); - return profiler; - } - - private static void enableTiming(RContext context, @SuppressWarnings("unused") boolean counting, boolean timing) { - Profiler profiler = getProfiler(context); - context.getInstrumentationState().setProfiler(profiler); - profiler.setTiming(timing); - profiler.setCollecting(true); - } - - /** - * (Interactively) installs a timer for a specific function. Currently the {@link Profiler} does - * not support profiling limited to specific functions so this effectively enables everything. - * If {@code func} is {@code null} profile all functions. In principle profiling can be - * restricted to entry counting and timing but currently counting is always on. - * - */ - public static void installTimer(@SuppressWarnings("unused") RFunction func, boolean counting, boolean timing) { - enableTiming(RContext.getInstance(), counting, timing); - } - - public static Counter getCounter(RFunction func) { - Profiler profiler = getProfiler(); - if (profiler.isCollecting()) { - String funcName = func.getTarget().getRootNode().getName(); - Map<SourceSection, Counter> counters = profiler.getCounters(); - for (Counter counter : counters.values()) { - if (counter.getName().equals(funcName)) { - return counter; - } - } - } - return null; - } - - public static void reset() { - Profiler profiler = getProfiler(); - profiler.clearData(); - profiler.setCollecting(false); - } - - public static void clear() { - Profiler profiler = getProfiler(); - profiler.clearData(); - } - - public static Counter[] getCounters() { - Profiler profiler = getProfiler(); - if (profiler.isCollecting()) { - Map<SourceSection, Counter> counters = profiler.getCounters(); - Counter[] result = new Counter[counters.size()]; - counters.values().toArray(result); - return result; - } else { - return null; - } - } - - public static boolean isTiming() { - Profiler profiler = getProfiler(); - return profiler.isTiming(); - } - - private static class PerfHandler implements RPerfStats.Handler { - static final String NAME = "timing"; - @SuppressWarnings("unused") private boolean stmts; - private int threshold; - - @Override - public void initialize(String optionText) { - if (optionText.length() > 0) { - String[] subOptions = optionText.split(":"); - for (String subOption : subOptions) { - if (subOption.equals("stmts")) { - Utils.warn("statement timing is not implemented"); - stmts = true; - } else if (subOption.startsWith("threshold")) { - threshold = Integer.parseInt(subOption.substring(subOption.indexOf('=') + 1)) * 1000; - } - } - } - } - - @Override - public String getName() { - return NAME; - } - - private static class SortableCounter implements Comparable<SortableCounter> { - private Counter counter; - - SortableCounter(Counter counter) { - this.counter = counter; - } - - @Override - public int compareTo(SortableCounter other) { - long myTime = counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED); - long otherTime = other.counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED); - return myTime < otherTime ? 1 : (myTime > otherTime ? -1 : 0); - } - - } - - /** - * Report the statement timing information at the end of the run. The report is per function - * Functions that consumed less time than requested threshold (default 0) are not included - * in the report. The report is sorted by cumulative time. - */ - @Override - public void report() { - Profiler profiler = RContext.getInstance().getInstrumentationState().getProfiler(); - // profiler.printHistograms(RPerfStats.out()); - Map<SourceSection, Counter> counters = profiler.getCounters(); - long totalTime = 0; - SortableCounter[] sortedCounters = new SortableCounter[counters.size()]; - int i = 0; - for (Counter counter : counters.values()) { - totalTime += counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED); - sortedCounters[i++] = new SortableCounter(counter); - } - Arrays.sort(sortedCounters); - for (SortableCounter scounter : sortedCounters) { - long time = scounter.counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED); - if (time > 0 && time > threshold) { - SourceSection ss = scounter.counter.getSourceSection(); - Source source = ss.getSource(); - RPerfStats.out().println("=========="); - double thisPercent = percent(time, totalTime); - RPerfStats.out().printf("%d ms (%.2f%%): %s, %s%n", time, thisPercent, scounter.counter.getName(), RSource.getOrigin(source)); - } - } - System.console(); - } - - private static double percent(long a, long b) { - return ((double) a * 100) / b; - } - - } -} 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 25bf947a8304aebda46b083aa8fe12e93397d044..476d02bada8e22c5d41723fd882cdb0bbc2266ac 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 @@ -96,14 +96,11 @@ public class RInstrumentation { * Activate the instrumentation system for {@code context}. Currently this simply checks for the * global (command-line) options for tracing and timing. They are applied to every context. */ - public static void activate(RContext context) { + public static void activate(@SuppressWarnings("unused") RContext context) { String rdebugValue = FastROptions.Rdebug.getStringValue(); if (rdebugValue != null) { debugFunctionNames = rdebugValue.split(","); } - if (RFunctionProfiler.enabled()) { - RFunctionProfiler.installTimers(context); - } // Check for function tracing RContext.getRRuntimeASTAccess().traceAllFunctions(); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java index 7863264c41c0e4d51d6e4b53920933e67a4e983e..733648fbaea8f503607b1b735e07275a000315ab 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java @@ -23,7 +23,6 @@ import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.RASTUtils; 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.signature.RArgumentsNode; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RFunction; @@ -37,7 +36,6 @@ public abstract class DispatchGeneric extends RBaseNode { private final ConditionProfile singleStringProfile = ConditionProfile.createBinaryProfile(); private final BranchProfile equalsMethodRequired = BranchProfile.create(); - @Child private RArgumentsNode argsNode = RArgumentsNode.create(); @Child private LoadMethod loadMethod = LoadMethodNodeGen.create(); @Child private ExecuteMethod executeMethod = new ExecuteMethod(); 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 72a4c84ab2dcfdc2f42b28b3d0a4a3ed09b55855..64bb9faef97b5e45e360939675c1bacd95455be1 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 @@ -14,11 +14,9 @@ package com.oracle.truffle.r.nodes.objects; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.Truffle; 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.DirectCallNode; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; @@ -29,7 +27,7 @@ import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.attributes.AttributeAccess; import com.oracle.truffle.r.nodes.attributes.AttributeAccessNodeGen; -import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; +import com.oracle.truffle.r.nodes.function.call.CallRFunctionNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RError; @@ -58,9 +56,8 @@ abstract class LoadMethod extends RBaseNode { @Child private WriteLocalFrameVariableNode writeRMethod = WriteLocalFrameVariableNode.create(RRuntime.R_DOT_METHOD, null, WriteVariableNode.Mode.REGULAR); @Child private LocalReadVariableNode methodsEnvRead = LocalReadVariableNode.create("methods", true); @Child private ReadVariableNode loadMethodFind; - @Child private DirectCallNode loadMethodCall; + @Child private CallRFunctionNode loadMethodCall; @CompilationFinal private RFunction loadMethodFunction; - @Child private RArgumentsNode argsNode = RArgumentsNode.create(); private final ConditionProfile cached = ConditionProfile.createBinaryProfile(); private final ConditionProfile moreAttributes = ConditionProfile.createBinaryProfile(); private final ConditionProfile noNextMethodAttr = ConditionProfile.createBinaryProfile(); @@ -119,7 +116,7 @@ abstract class LoadMethod extends RBaseNode { loadMethodFind = insert(ReadVariableNode.createFunctionLookup(RSyntaxNode.INTERNAL, RRuntime.R_LOAD_METHOD_NAME)); currentFunction = (RFunction) loadMethodFind.execute(frame, methodsEnv.getFrame()); loadMethodFunction = currentFunction; - loadMethodCall = insert(Truffle.getRuntime().createDirectCallNode(loadMethodFunction.getTarget())); + loadMethodCall = insert(CallRFunctionNode.create(loadMethodFunction.getTarget())); RError.performanceWarning("loadMethod executing slow path"); } else { currentFunction = (RFunction) loadMethodFind.execute(frame, methodsEnv.getFrame(methodsFrameAccessProfile)); @@ -129,10 +126,8 @@ abstract class LoadMethod extends RBaseNode { if (cached.profile(currentFunction == loadMethodFunction)) { // TODO: technically, someone could override loadMethod function and access the // caller, but it's rather unlikely - Object[] args = argsNode.execute(loadMethodFunction, caller, null, - new Object[]{fdef, fname, REnvironment.frameToEnvironment(frame.materialize())}, SIGNATURE, - null); - ret = (RFunction) loadMethodCall.call(frame, args); + ret = (RFunction) loadMethodCall.execute(frame, loadMethodFunction, caller, null, new Object[]{fdef, fname, REnvironment.frameToEnvironment(frame.materialize())}, SIGNATURE, + loadMethodFunction.getEnclosingFrame(), null); } else { // slow path ret = (RFunction) RContext.getEngine().evalFunction(currentFunction, frame.materialize(), caller, null, fdef, fname, REnvironment.frameToEnvironment(frame.materialize())); 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 9cb4f0d2939053290bf23227eea5ed16281774fb..bb33f7c87e692865c85bb056adbd3b6cb32987b2 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,9 +22,9 @@ */ 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.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.LoopConditionProfile; import com.oracle.truffle.r.nodes.attributes.CopyAttributesNode; @@ -73,7 +73,7 @@ public final class BinaryMapNode extends RBaseNode { private final ConditionProfile maxLengthProfile; private final ConditionProfile leftIsNAProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile rightIsNAProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile seenEmpty = BranchProfile.create(); + private final ConditionProfile seenEmpty = ConditionProfile.createBinaryProfile(); private final ConditionProfile shareLeft; private final ConditionProfile shareRight; private final RType argumentType; @@ -229,16 +229,16 @@ 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(left.hasDimensions() && right.hasDimensions()))) { if (differentDimensions(left, right)) { + CompilerDirectives.transferToInterpreter(); throw RError.error(this, RError.Message.NON_CONFORMABLE_ARRAYS); } } - if (leftLength == 0 || rightLength == 0) { + if (seenEmpty.profile(leftLength == 0 || rightLength == 0)) { /* * It is safe to skip attribute handling here as they are never copied if length is 0 of * either side. Note that dimension check still needs to be performed. */ - seenEmpty.enter(); return resultType.getEmpty(); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.java index 1c779089684ab3f4405a4289a2279be02d557295..95c12bd9fa164c812483478877d00b4ae380a07f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.java @@ -170,17 +170,21 @@ public final class UnaryMapNode extends RBaseNode { if (containsMetadata(operand) && operand != target) { hasAttributesProfile.enter(); result = result.materialize(); - copyAttributesInternal((RVector) result, operand); + copyAttributesInternal((RVector<?>) result, operand); } return result; } + private final ConditionProfile hasDimensionsProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile hasNamesProfile = ConditionProfile.createBinaryProfile(); + private boolean containsMetadata(RAbstractVector vector) { - return vector instanceof RVector && (vector.hasDimensions() || vector.getAttributes() != null || vector.getNames(attrProfiles) != null || vector.getDimNames(attrProfiles) != null); + return vector instanceof RVector && (hasDimensionsProfile.profile(vector.hasDimensions()) || vector.getAttributes() != null || hasNamesProfile.profile(vector.getNames(attrProfiles) != null) || + vector.getDimNames(attrProfiles) != null); } @TruffleBoundary - private void copyAttributesInternal(RVector result, RAbstractVector attributeSource) { + private void copyAttributesInternal(RVector<?> result, RAbstractVector attributeSource) { result.copyRegAttributesFrom(attributeSource); result.setDimensions(attributeSource.getDimensions()); result.copyNamesFrom(attrProfiles, attributeSource); 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 new file mode 100644 index 0000000000000000000000000000000000000000..2493bca82e507ee17f8dfe0450e1c0ac5c69220f --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/BypassNode.java @@ -0,0 +1,241 @@ +/* + * 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.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.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) { + return afterFindFirst.execute(value); + } 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) { + return noHead ? x : wrappedHead.execute(x); + } + + 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 9f401aa09158f569c14c17be0220dbd234d13d1e..e9b89627095e03cd06329d0eee7a0082a7ea2ab5 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 @@ -93,7 +93,7 @@ public abstract class CastBaseNode extends CastNode { } } - protected void preserveDimensionNames(RAbstractContainer operand, RVector ret) { + protected void preserveDimensionNames(RAbstractContainer operand, RVector<?> ret) { if (preserveDimensions()) { RList dimNames = operand.getDimNames(attrProfiles); if (hasDimNamesProfile.profile(dimNames != null)) { 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 2e6fae29105ba85c5233d5ed27c7ec804b8173a1..1ff2e13b0783bb648a3e3f246d8722b5a93a46ad 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 @@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.unary; import java.util.function.IntFunction; +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; @@ -34,6 +35,7 @@ import com.oracle.truffle.r.runtime.RType; 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.RList; import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRaw; @@ -41,6 +43,7 @@ import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; import com.oracle.truffle.r.runtime.ops.na.NAProfile; @@ -63,6 +66,16 @@ public abstract class CastComplexNode extends CastBaseNode { super(preserveNames, preserveDimensions, preserveAttributes); } + @Child private CastComplexNode recursiveCastComplex; + + private Object castComplexRecursive(Object o) { + if (recursiveCastComplex == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + recursiveCastComplex = insert(CastComplexNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes())); + } + return recursiveCastComplex.executeComplex(o); + } + @Override protected final RType getTargetType() { return RType.Complex; @@ -198,6 +211,50 @@ public abstract class CastComplexNode extends CastBaseNode { return createResultVector(operand, index -> RDataFactory.createComplex(operand.getDataAt(index).getValue(), 0)); } + @Specialization + protected RComplexVector doList(RAbstractListVector list) { + int length = list.getLength(); + double[] result = new double[length * 2]; + boolean seenNA = false; + for (int i = 0, j = 0; i < length; i++, j += 2) { + Object entry = list.getDataAt(i); + if (entry instanceof RList) { + result[j] = RRuntime.DOUBLE_NA; + result[j + 1] = RRuntime.DOUBLE_NA; + seenNA = true; + } else { + Object castEntry = castComplexRecursive(entry); + if (castEntry instanceof RComplex) { + RComplex value = (RComplex) castEntry; + result[j] = value.getRealPart(); + result[j + 1] = value.getImaginaryPart(); + seenNA = seenNA || RRuntime.isNA(value); + } else if (castEntry instanceof RComplexVector) { + RComplexVector complexVector = (RComplexVector) castEntry; + if (complexVector.getLength() == 1) { + RComplex value = complexVector.getDataAt(0); + result[j] = value.getRealPart(); + result[j + 1] = value.getImaginaryPart(); + seenNA = seenNA || RRuntime.isNA(value); + } else if (complexVector.getLength() == 0) { + result[j] = RRuntime.DOUBLE_NA; + result[j + 1] = RRuntime.DOUBLE_NA; + seenNA = true; + } else { + throw throwCannotCoerceListError("complex"); + } + } else { + throw throwCannotCoerceListError("complex"); + } + } + } + RComplexVector ret = RDataFactory.createComplexVector(result, !seenNA); + if (preserveAttributes()) { + ret.copyRegAttributesFrom(list); + } + return ret; + } + public static CastComplexNode create() { return CastComplexNodeGen.create(true, true, true); } 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 c4377e38e2f9e050931b613a7f2e815cb8fb1bac..fa706c4d013c7a781391beb75912f55a7f8fe5ce 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 @@ -30,6 +30,7 @@ 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.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.ops.na.NACheck; @@ -63,6 +64,11 @@ public abstract class CastDoubleBaseNode extends CastBaseNode { return RNull.instance; } + @Specialization + protected RMissing doMissing(RMissing missing) { + return missing; + } + @Specialization protected double doInt(int operand) { naCheck.enable(operand); 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 47459c84f748ba2d2c43a1eaeb17820d77e69ecb..9e5e541a9d2839cd2ac67f88b782a58a864ec385 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 @@ -38,7 +38,9 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; 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; @@ -58,8 +60,8 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { return recursiveCastDouble.executeDouble(o); } - private RDoubleVector createResultVector(RAbstractVector operand, double[] ddata) { - RDoubleVector ret = RDataFactory.createDoubleVector(ddata, naCheck.neverSeenNA(), getPreservedDimensions(operand), getPreservedNames(operand)); + private RDoubleVector vectorCopy(RAbstractContainer operand, double[] data, boolean isComplete) { + RDoubleVector ret = RDataFactory.createDoubleVector(data, isComplete, getPreservedDimensions(operand), getPreservedNames(operand)); preserveDimensionNames(operand, ret); if (preserveAttributes()) { ret.copyRegAttributesFrom(operand); @@ -76,12 +78,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { ddata[i] = value; seenNA = seenNA || naProfile.isNA(value); } - RDoubleVector ret = RDataFactory.createDoubleVector(ddata, !seenNA, getPreservedDimensions(operand), getPreservedNames(operand)); - preserveDimensionNames(operand, ret); - if (preserveAttributes()) { - ret.copyRegAttributesFrom(operand); - } - return ret; + return vectorCopy(operand, ddata, !seenNA); } @Specialization @@ -146,7 +143,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { warningBranch.enter(); RError.warning(this, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); } - return createResultVector(operand, ddata); + return vectorCopy(operand, ddata, naCheck.neverSeenNA()); } @Specialization @@ -160,12 +157,13 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { } @Specialization - protected RDoubleSequence doDoubleSequence(RDoubleSequence operand) { + protected RDoubleSequence doDoubleVector(RDoubleSequence operand) { + // sequence does not have attributes - nothing to copy or drop return operand; } @Specialization - protected RDoubleVector doList(RList list) { + protected RDoubleVector doList(RAbstractListVector list) { int length = list.getLength(); double[] result = new double[length]; boolean seenNA = false; 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 10e7fe8bfe7acb9b5388f997afb9859a29b56e53..60f816057c901fbe6863f0c7cc5460d7c54c4cf1 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 @@ -94,18 +94,14 @@ public abstract class CastExpressionNode extends CastBaseNode { if (obj instanceof RList) { RList list = (RList) obj; // TODO other attributes - return RDataFactory.createExpression(RDataFactory.createList(data, list.getNames(attrProfiles))); + return RDataFactory.createExpression(data, list.getNames(attrProfiles)); } else { - return create(data); + return RDataFactory.createExpression(data); } } private static RExpression create(Object obj) { - return create(new Object[]{obj}); - } - - private static RExpression create(Object[] objArray) { - return RDataFactory.createExpression(RDataFactory.createList(objArray)); + return RDataFactory.createExpression(new Object[]{obj}); } public static CastExpressionNode createNonPreserving() { 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 60d21ca021724d29ff2cf57c4277b96bf3088208..59245636fa3c80316e0febe0fa94e27645bd9ebe 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 @@ -61,18 +61,24 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { public abstract Object executeInt(Object o); @Specialization - protected RAbstractIntVector doIntVector(RAbstractIntVector operand) { + protected RIntVector doIntVector(RIntVector operand) { + return operand; + } + + @Specialization + protected RIntSequence doIntVector(RIntSequence operand) { + // sequence does not have attributes - nothing to copy or drop return operand; } @Specialization protected RIntSequence doDoubleSequence(RDoubleSequence operand) { - naCheck.enable(operand); - return RDataFactory.createIntSequence(naCheck.convertDoubleToInt(operand.getStart()), naCheck.convertDoubleToInt(operand.getStride()), operand.getLength()); + // start and stride cannot be NA so no point checking + return RDataFactory.createIntSequence(RRuntime.double2intNoCheck(operand.getStart()), RRuntime.double2intNoCheck(operand.getStride()), operand.getLength()); } - private RIntVector createResultVector(RAbstractVector operand, int[] idata) { - RIntVector ret = RDataFactory.createIntVector(idata, naCheck.neverSeenNA(), getPreservedDimensions(operand), getPreservedNames(operand)); + private RIntVector vectorCopy(RAbstractVector operand, int[] idata, boolean isComplete) { + RIntVector ret = RDataFactory.createIntVector(idata, isComplete, getPreservedDimensions(operand), getPreservedNames(operand)); preserveDimensionNames(operand, ret); if (preserveAttributes()) { ret.copyRegAttributesFrom(operand); @@ -94,12 +100,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { idata[i] = value; seenNA = seenNA || naProfile.isNA(value); } - RIntVector ret = RDataFactory.createIntVector(idata, !seenNA, getPreservedDimensions(operand), getPreservedNames(operand)); - preserveDimensionNames(operand, ret); - if (preserveAttributes()) { - ret.copyRegAttributesFrom(operand); - } - return ret; + return vectorCopy(operand, idata, !seenNA); } @Specialization @@ -119,7 +120,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { warningBranch.enter(); RError.warning(this, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); } - return createResultVector(operand, idata); + return vectorCopy(operand, idata, naCheck.neverSeenNA()); } @Specialization @@ -150,12 +151,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { if (warning) { RError.warning(this, RError.Message.NA_INTRODUCED_COERCION); } - RIntVector ret = RDataFactory.createIntVector(idata, !seenNA, getPreservedDimensions(operand), getPreservedNames(operand)); - preserveDimensionNames(operand, ret); - if (preserveAttributes()) { - ret.copyRegAttributesFrom(operand); - } - return ret; + return vectorCopy(operand, idata, !seenNA); } @Specialization @@ -166,7 +162,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { @Specialization protected RIntVector doDoubleVector(RAbstractDoubleVector operand) { naCheck.enable(operand); - return createResultVector(operand, naCheck.convertDoubleVectorToIntData(operand)); + return vectorCopy(operand, naCheck.convertDoubleVectorToIntData(operand), naCheck.neverSeenNA()); } @Specialization 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 8a67bbad26382d5854dc1d232ea40b558f2bbd9f..067eaf21145c014a299bf9d91fbafef902b3c2c1 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 @@ -32,7 +32,6 @@ import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributes; import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; import com.oracle.truffle.r.runtime.data.RDataFactory; -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.RList; @@ -86,11 +85,6 @@ public abstract class CastListNode extends CastBaseNode { return ret; } - @Specialization - protected RList doExpression(RExpression operand) { - return operand.getList(); - } - @Specialization protected RList doLanguage(RLanguage operand) { RList result = RContext.getRRuntimeASTAccess().asList(operand); 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 b7eac7f903810077889f3957e746be082c3a64c6..bb333f788f9fe878b320be956239f66f7cf84399 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 @@ -39,6 +39,7 @@ import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ops.na.NAProfile; @@ -79,6 +80,15 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { byte apply(int value); } + private RLogicalVector vectorCopy(RAbstractVector operand, byte[] bdata, boolean isComplete) { + RLogicalVector ret = RDataFactory.createLogicalVector(bdata, isComplete, getPreservedDimensions(operand), getPreservedNames(operand)); + preserveDimensionNames(operand, ret); + if (preserveAttributes()) { + ret.copyRegAttributesFrom(operand); + } + return ret; + } + private RLogicalVector createResultVector(RAbstractVector operand, IntToByteFunction elementFunction) { naCheck.enable(operand); byte[] bdata = new byte[operand.getLength()]; @@ -88,12 +98,7 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { bdata[i] = value; seenNA = seenNA || naProfile.isNA(value); } - RLogicalVector ret = RDataFactory.createLogicalVector(bdata, !seenNA, getPreservedDimensions(operand), getPreservedNames(operand)); - preserveDimensionNames(operand, ret); - if (preserveAttributes()) { - ret.copyRegAttributesFrom(operand); - } - return ret; + return vectorCopy(operand, bdata, !seenNA); } @Specialization @@ -134,7 +139,7 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { } @Specialization - protected RLogicalVector doList(RList list) { + protected RLogicalVector doList(RAbstractListVector list) { int length = list.getLength(); byte[] result = new byte[length]; boolean seenNA = false; 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 463283d4f62ec3068a9dc0f947249dc5457121b8..e1cf552841438ed5a9db695474689766d2054c7b 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 @@ -22,10 +22,11 @@ */ 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.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** @@ -34,12 +35,27 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; */ public abstract class CastNode extends UnaryNode { + private static boolean isTesting = false; + private static String lastWarning; + + public static void testingMode() { + isTesting = true; + } + + /** + * For testing purposes only, returns the last warning message (only when {@link #testingMode()} + * was invoked before). + */ + public static String getLastWarning() { + return lastWarning; + } + @TruffleBoundary protected static void handleArgumentError(Object arg, RBaseNode callObj, RError.Message message, Object[] messageArgs) { - if (RContext.getInstance() == null) { - throw new IllegalArgumentException(String.format(message.message, CastBuilder.substituteArgPlaceholder(arg, messageArgs))); + if (isTesting) { + throw new IllegalArgumentException(String.format(message.message, substituteArgPlaceholder(arg, messageArgs))); } else { - throw RError.error(callObj, message, CastBuilder.substituteArgPlaceholder(arg, messageArgs)); + throw RError.error(callObj, message, substituteArgPlaceholder(arg, messageArgs)); } } @@ -49,11 +65,24 @@ public abstract class CastNode extends UnaryNode { return; } - if (RContext.getInstance() == null) { - System.err.println(String.format(message.message, CastBuilder.substituteArgPlaceholder(arg, - messageArgs))); + if (isTesting) { + lastWarning = String.format(message.message, substituteArgPlaceholder(arg, messageArgs)); } else { - RError.warning(callObj, message, CastBuilder.substituteArgPlaceholder(arg, messageArgs)); + RError.warning(callObj, message, substituteArgPlaceholder(arg, messageArgs)); } } + + @SuppressWarnings({"unchecked"}) + public static Object[] substituteArgPlaceholder(Object arg, Object[] messageArgs) { + Object[] newMsgArgs = Arrays.copyOf(messageArgs, messageArgs.length); + + for (int i = 0; i < messageArgs.length; i++) { + final Object msgArg = messageArgs[i]; + if (msgArg instanceof Function) { + newMsgArgs[i] = ((Function<Object, Object>) msgArg).apply(arg); + } + } + + return newMsgArgs; + } } 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 c4216503fa42031bb450494e4ca88ffeb4c3fad3..69d13990142a7dcd8d52515c28c579f65576df7a 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 @@ -22,6 +22,7 @@ */ 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; @@ -39,6 +40,7 @@ import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; import com.oracle.truffle.r.runtime.ops.na.NAProfile; @@ -52,11 +54,21 @@ public abstract class CastRawNode extends CastBaseNode { super(preserveNames, preserveDimensions, preserveAttributes); } + @Child private CastRawNode recursiveCastRaw; + @Override protected final RType getTargetType() { return RType.Raw; } + protected Object castRawRecursive(Object o) { + if (recursiveCastRaw == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + recursiveCastRaw = insert(CastRawNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes())); + } + return recursiveCastRaw.executeRaw(o); + } + public abstract Object executeRaw(int o); public abstract Object executeRaw(double o); @@ -135,7 +147,7 @@ public abstract class CastRawNode extends CastBaseNode { return RRaw.valueOf((byte) intRawValue); } - private RRawVector createResultVector(RAbstractVector operand, byte[] bdata) { + private RRawVector vectorCopy(RAbstractVector operand, byte[] bdata) { RRawVector ret = RDataFactory.createRawVector(bdata, getPreservedDimensions(operand), getPreservedNames(operand)); preserveDimensionNames(operand, ret); if (preserveAttributes()) { @@ -162,7 +174,7 @@ public abstract class CastRawNode extends CastBaseNode { if (warning) { RError.warning(this, RError.Message.OUT_OF_RANGE); } - return createResultVector(operand, bdata); + return vectorCopy(operand, bdata); } @Specialization @@ -182,7 +194,7 @@ public abstract class CastRawNode extends CastBaseNode { if (warning) { RError.warning(this, RError.Message.OUT_OF_RANGE); } - return createResultVector(operand, bdata); + return vectorCopy(operand, bdata); } @Specialization @@ -222,7 +234,7 @@ public abstract class CastRawNode extends CastBaseNode { if (outOfRangeWarning) { RError.warning(this, RError.Message.OUT_OF_RANGE); } - return createResultVector(operand, bdata); + return vectorCopy(operand, bdata); } @Specialization @@ -250,7 +262,7 @@ public abstract class CastRawNode extends CastBaseNode { if (outOfRangeWarning) { RError.warning(this, RError.Message.OUT_OF_RANGE); } - return createResultVector(operand, bdata); + return vectorCopy(operand, bdata); } @Specialization @@ -271,7 +283,7 @@ public abstract class CastRawNode extends CastBaseNode { if (warning) { RError.warning(this, RError.Message.OUT_OF_RANGE); } - return createResultVector(operand, bdata); + return vectorCopy(operand, bdata); } @Specialization @@ -279,6 +291,16 @@ public abstract class CastRawNode extends CastBaseNode { return operand; } + @Specialization + protected RRawVector doList(RAbstractListVector value) { + int length = value.getLength(); + RRawVector result = RDataFactory.createRawVector(length); + for (int i = 0; i < length; i++) { + result.updateDataAt(i, (RRaw) castRawRecursive(value.getDataAt(i))); + } + return result; + } + public static CastRawNode createNonPreserving() { return CastRawNodeGen.create(false, false, false); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringBaseNode.java index 9c2b21f546c2cebbf1f14bdb329233844cea2a06..e5d9f51ef3fab718a57ff9e386fefb80704bdec6 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringBaseNode.java @@ -25,6 +25,8 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.runtime.RType; 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; public abstract class CastStringBaseNode extends CastBaseNode { @@ -73,4 +75,14 @@ public abstract class CastStringBaseNode extends CastBaseNode { protected String doRaw(RRaw value) { return toString(value); } + + @Specialization + protected RNull doNull(@SuppressWarnings("unused") RNull operand) { + return RNull.instance; + } + + @Specialization + protected RMissing doMissing(RMissing missing) { + return missing; + } } 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 9a258c8124fc2ca1f264a0f054dc899b0c89acb0..da5fa75b82edb5968fa1f8067511b8ac59a71e12 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 @@ -26,23 +26,14 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RNull; 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.RAbstractVector; public abstract class CastStringNode extends CastStringBaseNode { - private final boolean convertEmptyVectorToNull; - - protected CastStringNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean convertEmptyVectorToNull) { + protected CastStringNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { super(preserveNames, preserveDimensions, preserveAttributes); - this.convertEmptyVectorToNull = convertEmptyVectorToNull; - } - - public boolean convertEmptyVectorToNull() { - return convertEmptyVectorToNull; } public abstract Object executeString(int o); @@ -53,22 +44,21 @@ public abstract class CastStringNode extends CastStringBaseNode { public abstract Object executeString(Object o); - @Specialization - protected RNull doNull(@SuppressWarnings("unused") RNull operand) { - return RNull.instance; - } - - @Specialization(guards = "vector.getLength() == 0") - protected Object doEmptyVector(@SuppressWarnings("unused") RAbstractVector vector) { - return convertEmptyVectorToNull ? RNull.instance : RDataFactory.createStringVector(0); + private RStringVector vectorCopy(RAbstractContainer operand, String[] data) { + RStringVector ret = RDataFactory.createStringVector(data, operand.isComplete(), getPreservedDimensions(operand), getPreservedNames(operand)); + preserveDimensionNames(operand, ret); + if (preserveAttributes()) { + ret.copyRegAttributesFrom(operand); + } + return ret; } - @Specialization(guards = "vector.getLength() != 0") + @Specialization protected RStringVector doStringVector(RStringVector vector) { return vector; } - @Specialization(guards = "operand.getLength() != 0") + @Specialization protected RStringVector doIntVector(RAbstractContainer operand) { String[] sdata = new String[operand.getLength()]; // conversions to character will not introduce new NAs @@ -80,12 +70,7 @@ public abstract class CastStringNode extends CastStringBaseNode { sdata[i] = toString(o); } } - RStringVector ret = RDataFactory.createStringVector(sdata, operand.isComplete(), getPreservedDimensions(operand), getPreservedNames(operand)); - preserveDimensionNames(operand, ret); - if (preserveAttributes()) { - ret.copyRegAttributesFrom(operand); - } - return ret; + return vectorCopy(operand, sdata); } @Specialization @@ -94,10 +79,10 @@ public abstract class CastStringNode extends CastStringBaseNode { } public static CastStringNode create() { - return CastStringNodeGen.create(false, true, true, true); + return CastStringNodeGen.create(true, true, true); } public static CastStringNode createNonPreserving() { - return CastStringNodeGen.create(false, false, false, false); + return CastStringNodeGen.create(false, false, false); } } 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 c567944d82dd273656521a82d5dbe8af7d79426c..58cd32ecd1419a22a1b37836b1c71025602e487f 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 @@ -58,6 +58,11 @@ public abstract class CastSymbolNode extends CastBaseNode { throw RError.error(this, RError.Message.INVALID_TYPE_LENGTH, "symbol", 0); } + @Specialization + protected RSymbol doSymbol(RSymbol value) { + return value; + } + @Specialization protected RSymbol doInteger(int value) { return asSymbol(toString(value)); 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 769ee3d5558aa4b64476b6a7476e3e90c4c7d0a5..92608cf7e342cce9085cf9b329b841ccb42fd2e3 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 @@ -26,6 +26,7 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RS4Object; import com.oracle.truffle.r.runtime.data.RSymbol; @@ -51,6 +52,12 @@ public abstract class CastToAttributableNode extends CastBaseNode { return RNull.instance; } + @Specialization + @SuppressWarnings("unused") + protected RMissing cast(RMissing rmissing) { + return RMissing.instance; + } + @Specialization protected RAttributable cast(RAbstractContainer container) { return container; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToContainerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToContainerNode.java index 7bd1fd595cbb70500660a57c559305252bb520e1..6446fb5726c4ac08915478f269ab4f1d5c101378 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToContainerNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToContainerNode.java @@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.runtime.RType; -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.RNull; @@ -61,11 +60,6 @@ public abstract class CastToContainerNode extends CastBaseNode { return vector; } - @Specialization - protected RExpression cast(RExpression expression) { - return expression; - } - @Specialization protected RLanguage cast(RLanguage lang) { return lang; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.java index 2e0e5f5c5ae78c015836bd20bc316f17a1bb1fe3..f4f299fa5e6f591b38bbb5bed7accdbe771d427c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.java @@ -25,21 +25,19 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.NodeField; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.runtime.data.RDataFactory; -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; -@NodeField(name = "nonVectorPreserved", type = boolean.class) +@NodeField(name = "preserveNonVector", type = boolean.class) public abstract class CastToVectorNode extends CastNode { - public abstract boolean isNonVectorPreserved(); + public abstract boolean isPreserveNonVector(); @Specialization protected Object castNull(@SuppressWarnings("unused") RNull rnull) { - if (isNonVectorPreserved()) { + if (isPreserveNonVector()) { return RNull.instance; } else { return RDataFactory.createList(); @@ -48,7 +46,7 @@ public abstract class CastToVectorNode extends CastNode { @Specialization protected Object castMissing(@SuppressWarnings("unused") RMissing missing) { - if (isNonVectorPreserved()) { + if (isPreserveNonVector()) { return RMissing.instance; } else { return RDataFactory.createList(); @@ -57,7 +55,7 @@ public abstract class CastToVectorNode extends CastNode { @Specialization protected Object castFunction(RFunction f) { - if (isNonVectorPreserved()) { + if (isPreserveNonVector()) { return f; } else { return RDataFactory.createList(); @@ -69,11 +67,6 @@ public abstract class CastToVectorNode extends CastNode { return vector; } - @Specialization - protected RList cast(RExpression expression) { - return expression.getList(); - } - public static CastToVectorNode create() { return CastToVectorNodeGen.create(false); } 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 6497ce2d999787c72eab7460b2db9add5ca82a16..f57e27e31b17d73474aea021360ff032bf113019 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 @@ -28,12 +28,22 @@ import com.oracle.truffle.api.nodes.NodeInfo; @NodeInfo(cost = NodeCost.NONE) public final class ChainedCastNode extends CastNode { + @FunctionalInterface + public interface CastNodeFactory { + CastNode create(); + } + + private final CastNodeFactory firstCastFact; + private final CastNodeFactory secondCastFact; + @Child private CastNode firstCast; @Child private CastNode secondCast; - public ChainedCastNode(CastNode firstCast, CastNode secondCast) { - this.firstCast = firstCast; - this.secondCast = secondCast; + public ChainedCastNode(CastNodeFactory firstCastFact, CastNodeFactory secondCastFact) { + this.firstCastFact = firstCastFact; + this.secondCastFact = secondCastFact; + this.firstCast = firstCastFact.create(); + this.secondCast = secondCastFact.create(); } @Override @@ -48,4 +58,12 @@ 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 4d4442785cacde16406952f80b72e079651dc076..b8cebe877798dabd1920bb2c54757a182ecbab58 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 @@ -23,12 +23,16 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.ArgumentFilter; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RNull; -@SuppressWarnings({"rawtypes", "unchecked"}) public abstract class ConditionalMapNode extends CastNode { - private final ArgumentFilter argFilter; + private final ArgumentFilter<?, ?> argFilter; + private final ConditionProfile conditionProfile = ConditionProfile.createBinaryProfile(); + @Child private CastNode trueBranch; @Child private CastNode falseBranch; @@ -38,7 +42,12 @@ public abstract class ConditionalMapNode extends CastNode { this.falseBranch = falseBranch; } - public ArgumentFilter getFilter() { + public static ConditionalMapNode create(ArgumentFilter<?, ?> argFilter, CastNode trueBranch, + CastNode falseBranch) { + return ConditionalMapNodeGen.create(argFilter, trueBranch, falseBranch); + } + + public ArgumentFilter<?, ?> getFilter() { return argFilter; } @@ -50,17 +59,23 @@ public abstract class ConditionalMapNode extends CastNode { return falseBranch; } - protected boolean doMap(Object x) { - return argFilter.test(x); + @Specialization + protected RNull executeNull(@SuppressWarnings("unused") RNull x) { + return RNull.instance; } - @Specialization(guards = "doMap(x)") - protected Object map(Object x) { - return trueBranch == null ? x : trueBranch.execute(x); + @Specialization + protected RMissing executeMissing(@SuppressWarnings("unused") RMissing x) { + return RMissing.instance; } - @Specialization(guards = "!doMap(x)") - protected Object noMap(Object x) { - return falseBranch == null ? x : falseBranch.execute(x); + @SuppressWarnings("unchecked") + @Specialization + protected Object executeRest(Object x) { + if (conditionProfile.profile(((ArgumentFilter<Object, Object>) argFilter).test(x))) { + return trueBranch == null ? x : trueBranch.execute(x); + } else { + return falseBranch == null ? x : falseBranch.execute(x); + } } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/DuplicateNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/DuplicateNode.java index b68f11c03ff6e2435e4bb90bb32e56eace8dc3b4..9e94fc4d50e99526d4c6f1e8b0707ffa5c9cdbee 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/DuplicateNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/DuplicateNode.java @@ -25,7 +25,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.r.runtime.RInternalError; -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.RLanguage; @@ -65,11 +64,6 @@ public abstract class DuplicateNode extends RBaseNode { return p.copy(); } - @Specialization - protected RExpression duplicate(RExpression e) { - return e.copy(); - } - @Specialization protected RLanguage duplicate(RLanguage l) { return l.copy(); 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 9d3d5d5c4031a8a182a18627e492dfa7c40bb4f5..7924c01c9b73d825940fcfcfb56870c0f7729e47 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,13 +22,15 @@ */ 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.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.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @SuppressWarnings({"rawtypes", "unchecked"}) @@ -42,6 +44,7 @@ public abstract class FilterNode extends CastNode { private final boolean isWarning; private final BranchProfile warningProfile = BranchProfile.create(); + private final ConditionProfile conditionProfile = ConditionProfile.createBinaryProfile(); @Child private BoxPrimitiveNode boxPrimitiveNode = BoxPrimitiveNodeGen.create(); @@ -54,6 +57,10 @@ public abstract class FilterNode extends CastNode { this.boxPrimitives = boxPrimitives; } + public static FilterNode create(ArgumentFilter<?, ?> filter, boolean isWarning, RBaseNode callObj, RError.Message message, Object[] messageArgs, boolean boxPrimitives) { + return FilterNodeGen.create(filter, isWarning, callObj, message, messageArgs, boxPrimitives); + } + public ArgumentFilter getFilter() { return filter; } @@ -73,14 +80,21 @@ public abstract class FilterNode extends CastNode { } } - @Specialization(guards = "evalCondition(x)") - protected Object onTrue(Object x) { - return x; + @Specialization + protected RNull executeNull(@SuppressWarnings("unused") RNull x) { + return RNull.instance; } - @Fallback - protected Object onFalse(Object x) { - handleMessage(x); + @Specialization + protected RMissing executeMissing(@SuppressWarnings("unused") RMissing x) { + return RMissing.instance; + } + + @Specialization + public Object executeRest(Object x) { + if (!conditionProfile.profile(evalCondition(x))) { + handleMessage(x); + } return x; } @@ -88,5 +102,4 @@ public abstract class FilterNode extends CastNode { Object y = boxPrimitives ? boxPrimitiveNode.execute(x) : x; return filter.test(y); } - } 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 50ce753077808f792c0deba7e8abf4e88ef567a5..b15d5556ee76210cfdb87d4af6be208289ea8fcb 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 @@ -22,13 +22,11 @@ */ package com.oracle.truffle.r.nodes.unary; -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.profiles.ValueProfile; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RSerialize; import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.nodes.RNode; @@ -40,19 +38,25 @@ public abstract class GetNonSharedNode extends RNode implements RSyntaxNode { private final ValueProfile shareableTypeProfile = ValueProfile.createClassProfile(); + protected abstract RNode getN(); + + @Override + protected RSyntaxNode getRSyntaxNode() { + return getN().asRSyntaxNode(); + } + @Specialization protected RTypedValue getNonShared(RShareable shareable) { return shareableTypeProfile.profile(shareable).getNonShared(); } - @Fallback - protected Object getNonShared(Object o) { - return o; + protected static boolean isRShareable(Object o) { + return o instanceof RShareable; } - @Override - public void serializeImpl(RSerialize.State state) { - throw RInternalError.unimplemented("serializeImpl"); + @Specialization(guards = "!isRShareable(o)") + protected Object getNonShared(Object o) { + return o; } @Override diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/InheritsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/InheritsNode.java index 6a7a2a0ed7e4d0073dac926dc7f045dc95a0fb98..5826e2c9e8a26fdfca94d84000f09d5f1f30a9d1 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/InheritsNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/InheritsNode.java @@ -30,14 +30,15 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; @TypeSystemReference(RTypes.class) public abstract class InheritsNode extends RBaseNode { - public abstract Object executeObject(Object x, Object what, byte which); + public abstract Object executeObject(Object x, Object what, boolean which); protected ClassHierarchyNode createClassHierarchy() { return ClassHierarchyNodeGen.create(true, true); } - @Specialization(guards = "!isTrue(which)") - protected byte doesInherit(Object x, RAbstractStringVector what, @SuppressWarnings("unused") byte which, @Cached("createClassHierarchy()") ClassHierarchyNode classHierarchy) { + @Specialization(guards = "!which") + protected byte doesInherit(Object x, RAbstractStringVector what, @SuppressWarnings("unused") boolean which, + @Cached("createClassHierarchy()") ClassHierarchyNode classHierarchy) { RStringVector hierarchy = classHierarchy.execute(x); for (int i = 0; i < what.getLength(); i++) { String whatString = what.getDataAt(i); @@ -50,8 +51,9 @@ public abstract class InheritsNode extends RBaseNode { return RRuntime.LOGICAL_FALSE; } - @Specialization(guards = "isTrue(which)") - protected RIntVector doesInheritWhich(Object x, RAbstractStringVector what, @SuppressWarnings("unused") byte which, @Cached("createClassHierarchy()") ClassHierarchyNode classHierarchy) { + @Specialization(guards = "which") + protected RIntVector doesInheritWhich(Object x, RAbstractStringVector what, @SuppressWarnings("unused") boolean which, + @Cached("createClassHierarchy()") ClassHierarchyNode classHierarchy) { RStringVector hierarchy = classHierarchy.execute(x); int[] data = new int[what.getLength()]; for (int i = 0; i < what.getLength(); i++) { @@ -65,8 +67,4 @@ public abstract class InheritsNode extends RBaseNode { } return RDataFactory.createIntVector(data, RDataFactory.COMPLETE_VECTOR); } - - protected static boolean isTrue(byte value) { - return RRuntime.fromLogical(value); - } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/MapNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/MapNode.java index 7b833c222c28f8cd3ddef6f7c8a6579425f7ed18..e914f791c7562cb8bd1db8e7cfddba8d4fbea53a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/MapNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/MapNode.java @@ -22,31 +22,27 @@ */ package com.oracle.truffle.r.nodes.unary; -import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.ArgumentMapper; -import com.oracle.truffle.r.runtime.data.RNull; @SuppressWarnings({"rawtypes", "unchecked"}) -public abstract class MapNode extends CastNode { +public final class MapNode extends CastNode { private final ArgumentMapper mapFn; - protected MapNode(ArgumentMapper<?, ?> mapFn) { + private MapNode(ArgumentMapper<?, ?> mapFn) { this.mapFn = mapFn; } - public ArgumentMapper getMapper() { - return mapFn; + public static MapNode create(ArgumentMapper<?, ?> mapFn) { + return new MapNode(mapFn); } - @Specialization - protected Object mapNull(RNull x) { - Object res = mapFn.map(null); - return res == null ? x : res; + public ArgumentMapper getMapper() { + return mapFn; } - @Specialization - protected Object map(Object x) { + @Override + public Object execute(Object x) { return mapFn.map(x); } } 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 6081c9cfc972e118a0cd72c5e199b6273d543e6a..32609b425ad8f99ae3bd140603ac9f9100b8df44 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 @@ -43,6 +43,7 @@ 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.RBaseNode; +import com.oracle.truffle.r.runtime.ops.na.NACheck; @TypeSystemReference(RTypes.class) public abstract class ToStringNode extends RBaseNode { @@ -51,6 +52,8 @@ public abstract class ToStringNode extends RBaseNode { @Child private ToStringNode recursiveToString; + private final NACheck naCheck = NACheck.create(); + private String toStringRecursive(Object o, boolean quotes, String separator) { if (recursiveToString == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -95,7 +98,8 @@ public abstract class ToStringNode extends RBaseNode { @SuppressWarnings("unused") @Specialization protected String toString(RComplex complex, boolean quotes, String separator) { - return complex.toString(); + naCheck.enable(complex); + return naCheck.convertComplexToString(complex); } @SuppressWarnings("unused") @@ -113,7 +117,8 @@ public abstract class ToStringNode extends RBaseNode { @SuppressWarnings("unused") @Specialization protected String toString(double operand, boolean quotes, String separator) { - return RRuntime.doubleToString(operand); + naCheck.enable(operand); + return naCheck.convertDoubleToString(operand); } @SuppressWarnings("unused") 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 e566ab4086f763a2730b8a600fd3d6c99a56a0a1..175f08ba663325d20de37f6492b6a90287d4d7b8 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 @@ -58,7 +58,7 @@ public abstract class TypeofNode extends UnaryNode { } @Specialization - protected static RType doString(RMissing x) { + protected static RType doMissing(RMissing x) { return RType.Missing; } 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 cc9aa1d5be5ec95f4d7f494dfcb86d592f2c67ee..051d011fb1f5ab2e285db54249a453f0f743681a 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 @@ -81,6 +81,8 @@ public class ParserGeneration { "transform parser to a generic class via the annotation processor", "use RComplex.createNA()", "inlined ParseUtils", - "properly throw errors in lexer" + "properly throw errors in lexer", + "remove deprecated calls to SourceSection functions", + "remove deprecated calls to Source functions" }; } 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 df8ab94e9a4bd4b75dc52cc178dffb4c2c0f856e..952f8f563419bf3ac9eff9e425f4cb4262668da3 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 @@ -90,7 +90,7 @@ package com.oracle.truffle.r.parser; private SourceSection src(Token t) { CommonToken token = (CommonToken) t; int startIndex = token.getStartIndex(); - return source.createSection(null, token.getLine(), token.getCharPositionInLine() + 1, startIndex, token.getStopIndex() - startIndex + 1); + return source.createSection(startIndex, token.getStopIndex() - startIndex + 1); } /** @@ -102,7 +102,7 @@ package com.oracle.truffle.r.parser; int startIndex = cstart.getStartIndex(); int stopIndex = cstop.getStopIndex(); int length = stopIndex - startIndex + (cstop.getType() == Token.EOF ? 0 : 1); - return source.createSection(null, cstart.getLine(), cstart.getCharPositionInLine() + 1, startIndex, length); + return source.createSection(startIndex, length); } // without this override, the parser will not throw exceptions if it can recover diff --git a/com.oracle.truffle.r.release/.project b/com.oracle.truffle.r.release/.project new file mode 100644 index 0000000000000000000000000000000000000000..c9dac31e549219d766cfa3db51ad2878005c638a --- /dev/null +++ b/com.oracle.truffle.r.release/.project @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>com.oracle.truffle.r.release</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name> + <triggers>full,incremental,</triggers> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.cdt.core.cnature</nature> + <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature> + <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature> + </natures> +</projectDescription> diff --git a/com.oracle.truffle.r.release/Makefile b/com.oracle.truffle.r.release/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..501dc0ff9bc4dd930cf79e6329a95d5296afaf6d --- /dev/null +++ b/com.oracle.truffle.r.release/Makefile @@ -0,0 +1,27 @@ +# +# Copyright (c) 2016, 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. +# + +all: + +clean: + rm -rf bin doc etc lib library share diff --git a/com.oracle.truffle.r.release/src/R_launcher b/com.oracle.truffle.r.release/src/R_launcher new file mode 100644 index 0000000000000000000000000000000000000000..d72f738599c9164737c3bd8dbbbcaa0c74320847 --- /dev/null +++ b/com.oracle.truffle.r.release/src/R_launcher @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +JAVA_ARGS=() +PROGRAM_ARGS=() +for opt in "${@:1}" +do + case $opt in + -J:*) + opt=${opt:3} + JAVA_ARGS+=("$opt") ;; + *) + PROGRAM_ARGS+=("$opt") ;; + esac +done + +exec java "${JAVA_ARGS[@]}" -cp %%CLASSPATH com.oracle.truffle.r.engine.shell.RCommand "${PROGRAM_ARGS[@]}" diff --git a/com.oracle.truffle.r.release/src/Rscript_launcher b/com.oracle.truffle.r.release/src/Rscript_launcher new file mode 100644 index 0000000000000000000000000000000000000000..e9d8fb7a4ec280ade7c9df61820157b5f0b9d73c --- /dev/null +++ b/com.oracle.truffle.r.release/src/Rscript_launcher @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +JAVA_ARGS=() +PROGRAM_ARGS=() +for opt in "${@:1}" +do + case $opt in + -J:*) + opt=${opt:3} + JAVA_ARGS+=("$opt") ;; + *) + PROGRAM_ARGS+=("$opt") ;; + esac +done + +# we can invoke FastR directly, but we do have to set R_HOME +R_HOME_DIR="$(dirname $0)/.." +export R_HOME="$(unset CDPATH && cd ${R_HOME_DIR} && pwd)" +exec java -cp %%CLASSPATH "${JAVA_ARGS[@]}" com.oracle.truffle.r.engine.shell.RscriptCommand "${PROGRAM_ARGS[@]}" diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/Load_RFFIFactory.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/Load_RFFIFactory.java index f178e6264add01001baa99864f8a290312dc9f6d..003cfc0e03d5cd67a3e6fde4468a32f33eed1fb3 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/Load_RFFIFactory.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/Load_RFFIFactory.java @@ -32,7 +32,7 @@ public class Load_RFFIFactory { private static final String FACTORY_CLASS_PROPERTY = "fastr.ffi.factory.class"; private static final String PACKAGE_PREFIX = "com.oracle.truffle.r.runtime.ffi."; private static final String SUFFIX = "_RFFIFactory"; - private static final String DEFAULT_FACTORY = "jnr"; + private static final String DEFAULT_FACTORY = "jni"; private static final String DEFAULT_FACTORY_CLASS = mapSimpleName(DEFAULT_FACTORY); private static String mapSimpleName(String simpleName) { diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java index 7aa097a1e35b9f594b1a7884d40cada004552cf0..0695d46b3a50b64b9664e158c287d9e44c03bafc 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java @@ -29,7 +29,7 @@ import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RUnboundValue; import com.oracle.truffle.r.runtime.env.REnvironment; -import com.oracle.truffle.r.runtime.ffi.jnr.CallRFFIHelper; +import com.oracle.truffle.r.runtime.ffi.jni.CallRFFIHelper; public enum RFFIVariables { R_Home(REnvVars.rHome()), diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java similarity index 94% rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java index d644738e48811feaa3e60840a01274d4506c88bf..3d6bbf5431b18850e1cb6488f3ad68289ca8c137 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java @@ -20,11 +20,9 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.ffi.jnr; +package com.oracle.truffle.r.runtime.ffi.jni; import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; import java.util.function.Function; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -35,17 +33,16 @@ import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RCleanUp; -import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.REnvVars; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RErrorHandling; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RSrcref; import com.oracle.truffle.r.runtime.RSource; +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.RStartParams.SA_TYPE; 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; @@ -92,7 +89,7 @@ import com.oracle.truffle.r.runtime.rng.RRNG; */ public class CallRFFIHelper { - private static final class CharSXPWrapper { + public static final class CharSXPWrapper { private final String contents; CharSXPWrapper(String contents) { @@ -351,7 +348,7 @@ public class CallRFFIHelper { public static void Rf_setAttrib(Object obj, Object name, Object val) { if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_setAttrib", obj, name); + RFFIUtils.traceUpCall("Rf_setAttrib", obj, name, val); } if (obj instanceof RAttributable) { RAttributable attrObj = (RAttributable) obj; @@ -678,13 +675,7 @@ public class CallRFFIHelper { } int code = SEXPTYPE.gnuRCodeForObject(x); if (code == SEXPTYPE.LISTSXP.code && v == SEXPTYPE.LANGSXP.code) { - RList l; - if (x instanceof RPairList) { - l = ((RPairList) x).toRList(); - } else { - l = (RList) x; - } - return RContext.getRRuntimeASTAccess().fromList(l, RLanguage.RepType.CALL); + return RLanguage.fromList(x, RLanguage.RepType.CALL); } else { throw unimplemented(); } @@ -771,16 +762,8 @@ public class CallRFFIHelper { } if (e instanceof RLanguage) { RLanguage lang = (RLanguage) e; - int length = RContext.getRRuntimeASTAccess().getLength(lang); - Object obj = RNull.instance; - - // TODO: missing argument names in the tags - for (int i = length - 1; i >= 1; i--) { - Object element = RContext.getRRuntimeASTAccess().getDataAtAsObject(lang, i); - obj = RDataFactory.createPairList(element, obj); - } - - return obj; + RPairList l = lang.getPairList(); + return l.cdr(); } else { guaranteeInstanceOf(e, RPairList.class); return ((RPairList) e).cdr(); @@ -805,16 +788,8 @@ public class CallRFFIHelper { } if (e instanceof RLanguage) { RLanguage lang = (RLanguage) e; - int length = RContext.getRRuntimeASTAccess().getLength(lang); - Object obj = RNull.instance; - - // TODO: missing argument names in the tags - for (int i = length - 1; i >= 2; i--) { - Object element = RContext.getRRuntimeASTAccess().getDataAtAsObject(lang, i); - obj = RDataFactory.createPairList(element, obj); - } - - return obj; + RPairList l = lang.getPairList(); + return l.cddr(); } else { guaranteeInstanceOf(e, RPairList.class); return ((RPairList) e).cddr(); @@ -905,18 +880,19 @@ public class CallRFFIHelper { if (expr instanceof RPromise) { result = RContext.getRRuntimeASTAccess().forcePromise(null, expr); } else if (expr instanceof RExpression) { - result = RContext.getEngine().eval((RExpression) expr, (REnvironment) env, topLevel); + result = RContext.getEngine().eval((RExpression) expr, (REnvironment) env, RCaller.topLevel); } else if (expr instanceof RLanguage) { - result = RContext.getEngine().eval((RLanguage) expr, (REnvironment) env, topLevel); + result = RContext.getEngine().eval((RLanguage) expr, (REnvironment) env, RCaller.topLevel); } else if (expr instanceof RPairList) { RPairList l = (RPairList) expr; RFunction f = (RFunction) l.car(); Object args = l.cdr(); if (args == RNull.instance) { - result = RContext.getEngine().evalFunction(f, env == REnvironment.globalEnv() ? null : ((REnvironment) env).getFrame(), topLevel, null, new Object[0]); + result = RContext.getEngine().evalFunction(f, env == REnvironment.globalEnv() ? null : ((REnvironment) env).getFrame(), RCaller.topLevel, null, new Object[0]); } else { RList argsList = ((RPairList) args).toRList(); - result = RContext.getEngine().evalFunction(f, env == REnvironment.globalEnv() ? null : ((REnvironment) env).getFrame(), topLevel, argsList.getNames(), argsList.getDataNonShared()); + result = RContext.getEngine().evalFunction(f, env == REnvironment.globalEnv() ? null : ((REnvironment) env).getFrame(), RCaller.topLevel, argsList.getNames(), + argsList.getDataNonShared()); } } else { @@ -1149,8 +1125,7 @@ public class CallRFFIHelper { return env.ls(all, null, sorted); } - @SuppressWarnings("unused") - private static String R_HomeDir() { + public static String R_HomeDir() { if (RFFIUtils.traceEnabled()) { RFFIUtils.traceUpCall("R_HomeDir"); } @@ -1168,18 +1143,20 @@ public class CallRFFIHelper { return x; } - private static RCaller topLevel = RCaller.createInvalid(null); - public static Object getGlobalContext() { + Utils.warn("Potential memory leak (global context object)"); if (RFFIUtils.traceEnabled()) { RFFIUtils.traceUpCall("getGlobalContext"); } Frame frame = Utils.getActualCurrentFrame(); if (frame == null) { - return topLevel; + return RCaller.topLevel; + } + if (RContext.getInstance().stateInstrumentation.getBrowserState().inBrowser()) { + return RContext.getInstance().stateInstrumentation.getBrowserState().getInBrowserCaller(); } RCaller rCaller = RArguments.getCall(frame); - return rCaller == null ? topLevel : rCaller; + return rCaller == null ? RCaller.topLevel : rCaller; } public static Object getGlobalEnv() { @@ -1252,6 +1229,7 @@ public class CallRFFIHelper { // Checkstyle: stop method name check public static Object R_getGlobalFunctionContext() { + Utils.warn("Potential memory leak (global function context object)"); if (RFFIUtils.traceEnabled()) { RFFIUtils.traceUpCall("getGlobalFunctionContext"); } @@ -1261,26 +1239,28 @@ public class CallRFFIHelper { } RCaller currentCaller = RArguments.getCall(frame); while (currentCaller != null) { - if (!currentCaller.isPromise() && currentCaller.isValidCaller()) { + if (!currentCaller.isPromise() && currentCaller.isValidCaller() && currentCaller != RContext.getInstance().stateInstrumentation.getBrowserState().getInBrowserCaller()) { break; } currentCaller = currentCaller.getParent(); } - return currentCaller == null || currentCaller == topLevel ? RNull.instance : currentCaller; + return currentCaller == null || currentCaller == RCaller.topLevel ? RNull.instance : currentCaller; } public static Object R_getParentFunctionContext(Object c) { + Utils.warn("Potential memory leak (parent function context object)"); if (RFFIUtils.traceEnabled()) { RFFIUtils.traceUpCall("getParentFunctionContext"); } RCaller currentCaller = guaranteeInstanceOf(c, RCaller.class); while (true) { currentCaller = currentCaller.getParent(); - if (currentCaller == null || (!currentCaller.isPromise() && currentCaller.isValidCaller())) { + if (currentCaller == null || + (!currentCaller.isPromise() && currentCaller.isValidCaller() && currentCaller != RContext.getInstance().stateInstrumentation.getBrowserState().getInBrowserCaller())) { break; } } - return currentCaller == null || currentCaller == topLevel ? RNull.instance : currentCaller; + return currentCaller == null || currentCaller == RCaller.topLevel ? RNull.instance : currentCaller; } public static Object R_getContextEnv(Object c) { @@ -1288,7 +1268,7 @@ public class CallRFFIHelper { RFFIUtils.traceUpCall("getContextEnv", c); } RCaller rCaller = guaranteeInstanceOf(c, RCaller.class); - if (rCaller == topLevel) { + if (rCaller == RCaller.topLevel) { return RContext.getInstance().stateREnvironment.getGlobalEnv(); } Frame frame = Utils.getActualCurrentFrame(); @@ -1316,7 +1296,7 @@ public class CallRFFIHelper { RFFIUtils.traceUpCall("getContextEnv", c); } RCaller rCaller = guaranteeInstanceOf(c, RCaller.class); - if (rCaller == topLevel) { + if (rCaller == RCaller.topLevel) { return RNull.instance; } Frame frame = Utils.getActualCurrentFrame(); @@ -1344,27 +1324,10 @@ public class CallRFFIHelper { RFFIUtils.traceUpCall("getContextEnv", c); } RCaller rCaller = guaranteeInstanceOf(c, RCaller.class); - if (rCaller == topLevel) { + if (rCaller == RCaller.topLevel) { return RNull.instance; } - Frame frame = Utils.getActualCurrentFrame(); - if (RArguments.getCall(frame) == rCaller) { - return RContext.getRRuntimeASTAccess().getSyntaxCaller(rCaller); - } else { - Object result = Utils.iterateRFrames(FrameAccess.READ_ONLY, new Function<Frame, Object>() { - - @Override - public Object apply(Frame f) { - RCaller currentCaller = RArguments.getCall(f); - if (currentCaller == rCaller) { - return RContext.getRRuntimeASTAccess().getSyntaxCaller(rCaller); - } else { - return null; - } - } - }); - return result; - } + return RContext.getRRuntimeASTAccess().getSyntaxCaller(rCaller); } public static Object R_getContextSrcRef(Object c) { @@ -1377,9 +1340,9 @@ public class CallRFFIHelper { } else { RFunction f = (RFunction) o; SourceSection ss = f.getRootNode().getSourceSection(); - String path = ss.getSource().getPath(); - return RSrcref.createLloc(ss, path); - + String path = RSource.getPath(ss.getSource()); + // TODO: is it OK to pass "" if path is null? + return RSrcref.createLloc(ss, path == null ? "" : path); } } @@ -1387,4 +1350,21 @@ public class CallRFFIHelper { public static int R_insideBrowser() { return RContext.getInstance().stateInstrumentation.getBrowserState().inBrowser() ? 1 : 0; } + + public static int R_isGlobal(Object c) { + if (RFFIUtils.traceEnabled()) { + RFFIUtils.traceUpCall("isGlobal", c); + } + RCaller rCaller = guaranteeInstanceOf(c, RCaller.class); + + return rCaller == RCaller.topLevel ? 1 : 0; + } + + public static int R_isEqual(Object x, Object y) { + if (RFFIUtils.traceEnabled()) { + RFFIUtils.traceUpCall("isEqual", x, y); + } + return x == y ? 1 : 0; + } + } diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Base.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Base.java new file mode 100644 index 0000000000000000000000000000000000000000..ca874253e76c4bbd00c8d568e7d74f6d9f32fd20 --- /dev/null +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Base.java @@ -0,0 +1,171 @@ +/* + * 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.runtime.ffi.jni; + +import java.io.IOException; +import java.util.ArrayList; + +import com.oracle.truffle.r.runtime.ffi.BaseRFFI; + +public class JNI_Base implements BaseRFFI { + @Override + public int getpid() { + return native_getpid(); + } + + @Override + public int setwd(String dir) { + return native_setwd(dir); + } + + @Override + public String getwd() { + byte[] buf = new byte[4096]; + int rc = native_getwd(buf, buf.length); + if (rc == 0) { + return null; + } else { + int i = 0; + while (buf[i] != 0 && i < buf.length) { + i++; + } + return new String(buf, 0, i); + } + } + + private static final int EINVAL = 22; + + @Override + public String readlink(String path) throws IOException { + int[] errno = new int[]{0}; + String s = native_readlink(path, errno); + if (s == null) { + if (errno[0] == EINVAL) { + // not a link + } else { + // some other error + throw new IOException("readlink failed: " + errno[0]); + } + } + return s; + } + + @Override + public String mkdtemp(String template) { + byte[] bytes = template.getBytes(); + long result = native_mkdtemp(bytes); + if (result == 0) { + return null; + } else { + return new String(bytes); + } + } + + @Override + public void mkdir(String dir, int mode) throws IOException { + int rc = native_mkdir(dir, mode); + if (rc != 0) { + throw new IOException("mkdir " + dir + " failed"); + } + } + + @Override + public int chmod(String path, int mode) { + return native_chmod(path, mode); + } + + @Override + public long strtol(String s, int base) throws IllegalArgumentException { + int[] errno = new int[]{0}; + long result = native_strtol(s, base, errno); + if (errno[0] != 0) { + throw new IllegalArgumentException("strtol failure"); + } else { + return result; + } + } + + @Override + public Object dlopen(String path, boolean local, boolean now) { + long handle = native_dlopen(path, local, now); + if (handle == 0) { + return null; + } else { + return new Long(handle); + } + } + + @Override + public long dlsym(Object handle, String symbol) { + long nativeHandle = (Long) handle; + return native_dlsym(nativeHandle, symbol); + } + + @Override + public int dlclose(Object handle) { + long nativeHandle = (Long) handle; + return native_dlclose(nativeHandle); + } + + @Override + public String dlerror() { + return native_dlerror(); + } + + @Override + public UtsName uname() { + return JNI_UtsName.get(); + } + + @Override + public ArrayList<String> glob(String pattern) { + return JNI_Glob.glob(pattern); + } + + // Checkstyle: stop method name + + private static native int native_getpid(); + + private static native int native_getwd(byte[] buf, int buflength); + + private static native int native_setwd(String dir); + + private static native int native_mkdtemp(byte[] template); + + private static native int native_mkdir(String dir, int mode); + + private static native int native_chmod(String dir, int mode); + + private static native long native_strtol(String s, int base, int[] errno); + + private static native String native_readlink(String s, int[] errno); + + private static native long native_dlopen(String path, boolean local, boolean now); + + private static native int native_dlclose(long handle); + + private static native String native_dlerror(); + + private static native long native_dlsym(long handle, String symbol); + +} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java new file mode 100644 index 0000000000000000000000000000000000000000..160d050b378b3748a88c9857f5ee1d310ca22a5a --- /dev/null +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java @@ -0,0 +1,43 @@ +/* + * 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.runtime.ffi.jni; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.runtime.ffi.CRFFI; + +public class JNI_C implements CRFFI { + + /** + * This is rather similar to {@link JNI_Call}, except the objects are guaranteed to be native + * array types, no upcalls are possible, and no result is returned. However, the receiving + * function expects actual native arrays (not SEXPs), so these have to be handled on the JNI + * side. + */ + @Override + @TruffleBoundary + public synchronized void invoke(long address, Object[] args) { + c(address, args); + } + + private static native void c(long address, Object[] args); +} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_CallRFFI.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java similarity index 94% rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_CallRFFI.java rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java index 70c2779c9081b931c2910f712446abeaa6de3022..3d3fb55004ac59ea96ab88cf9205b194a3000028 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_CallRFFI.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.ffi.jnr; +package com.oracle.truffle.r.runtime.ffi.jni; import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCall; import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCallReturn; @@ -28,6 +28,7 @@ import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceEnabled; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.ffi.BaseRFFI; import com.oracle.truffle.r.runtime.ffi.CallRFFI; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.DLL.DLLException; @@ -43,9 +44,9 @@ import com.oracle.truffle.r.runtime.ffi.RFFIVariables; * * The JNI layer is not (currently) MT safe, so all calls are single threaded. */ -public class JNI_CallRFFI implements CallRFFI { +public class JNI_Call implements CallRFFI { - JNI_CallRFFI() { + JNI_Call() { loadLibrary(); } @@ -57,9 +58,15 @@ public class JNI_CallRFFI implements CallRFFI { * {@code RTLD_LOCAL} with {@code dlopen}, so we have to load the library manually and set * {@code RTLD_GLOBAL}. However, a {@code dlopen} does not hook the JNI functions into the JVM, * so we have to do an additional {@code System.load} to achieve that. + * + * Before we do that we must load {@code libjniboot} because the implementation of + * {@link BaseRFFI#dlopen} is called by {@link DLL#load} which uses JNI! */ @TruffleBoundary private static void loadLibrary() { + String libjnibootPath = LibPaths.getBuiltinLibPath("jniboot"); + System.load(libjnibootPath); + String librffiPath = LibPaths.getBuiltinLibPath("R"); try { DLL.load(librffiPath, ForceRTLDGlobal, false); diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_Glob.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Glob.java similarity index 96% rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_Glob.java rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Glob.java index 111b1f6e308be889b7008e670320e2867555fc75..975294266f0d1753ac9b461960a528a681701b97 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_Glob.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Glob.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.ffi.jnr; +package com.oracle.truffle.r.runtime.ffi.jni; import java.util.ArrayList; 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 new file mode 100644 index 0000000000000000000000000000000000000000..83499ad00ca8cfff07359a0af4d40b9c7b405222 --- /dev/null +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2015, 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.ffi.jni; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.runtime.ffi.LapackRFFI; + +public class JNI_Lapack implements LapackRFFI { + @Override + @TruffleBoundary + public void ilaver(int[] version) { + native_ilaver(version); + } + + @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) { + return native_dgeev(jobVL, jobVR, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork); + } + + @Override + @TruffleBoundary + public int dgeqp3(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); + } + + @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) { + return native_dormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork); + } + + @Override + @TruffleBoundary + public int dtrtrs(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); + } + + @Override + @TruffleBoundary + public int dgetrf(int m, int n, double[] a, int lda, int[] ipiv) { + return native_dgetrf(m, n, a, lda, ipiv); + } + + @Override + @TruffleBoundary + public int dpotrf(char uplo, int n, double[] a, int lda) { + return native_dpotrf(uplo, n, a, lda); + } + + @Override + @TruffleBoundary + public int dpstrf(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); + } + + @Override + @TruffleBoundary + public int dgesv(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) { + return native_dgesv(n, nrhs, a, lda, ipiv, b, ldb); + } + + @Override + @TruffleBoundary + public double dlange(char norm, int m, int n, double[] a, int lda, double[] work) { + return native_dlange(norm, m, n, a, lda, work); + } + + @Override + @TruffleBoundary + public int dgecon(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); + } + + // Checkstyle: stop method name + + private static native void native_ilaver(int[] version); + + private static native int native_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); + + private static native int native_dgeqp3(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork); + + private static native int native_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); + + private static native int native_dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb); + + private static native int native_dgetrf(int m, int n, double[] a, int lda, int[] ipiv); + + private static native int native_dpotrf(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); + + private static native double native_dlange(char norm, int m, int n, double[] a, int lda, double[] work); + + private static native int native_dgecon(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork); + +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..eb9acfc8566c51815bdb537e07d5a842ddb8bad8 --- /dev/null +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016, 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.ffi.jni; + +import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCall; +import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCallReturn; +import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceEnabled; + +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 { + if (traceEnabled()) { + traceDownCallReturn("exactSum", null); + } + } + } + + 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_PCRE.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java new file mode 100644 index 0000000000000000000000000000000000000000..7a73c6d80b18230d776b2beee7da57ad770a8862 --- /dev/null +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015, 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.ffi.jni; + +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.ffi.PCRERFFI; + +public class JNI_PCRE implements PCRERFFI { + @Override + public long maketables() { + return nativeMaketables(); + } + + @Override + public Result compile(String pattern, int options, long tables) { + return nativeCompile(pattern, options, tables); + } + + @Override + public Result study(long code, int options) { + throw RInternalError.unimplemented("pcre_study"); + } + + @Override + public int exec(long code, long extra, String subject, int offset, int options, int[] ovector) { + return nativeExec(code, extra, subject, offset, options, ovector, ovector.length); + } + + private static native long nativeMaketables(); + + private static native Result nativeCompile(String pattern, int options, long tables); + + private static native int nativeExec(long code, long extra, String subject, int offset, + int options, int[] ovector, int ovectorLen); + +} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_PkgInit.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java similarity index 98% rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_PkgInit.java rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java index 4576a66fdf3cec66e4430969573602e730985521..a93b6008d661a12ba9887a5d948bf7f0f6a06c6c 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_PkgInit.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.ffi.jnr; +package com.oracle.truffle.r.runtime.ffi.jni; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.ffi.DLL; 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 new file mode 100644 index 0000000000000000000000000000000000000000..b48a2fa9c113c12f68a2632ee147f1b3c55c4287 --- /dev/null +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java @@ -0,0 +1,55 @@ +/* + * 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.runtime.ffi.jni; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.runtime.ffi.RApplRFFI; + +public class JNI_RAppl implements RApplRFFI { + @Override + @TruffleBoundary + public void dqrdc2(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); + } + + @Override + @TruffleBoundary + public void dqrcf(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); + } + + @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) { + native_dqrls(x, n, p, y, ny, tol, b, rsd, qty, k, jpvt, qraux, work); + } + + // 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); + + private static native void native_dqrcf(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info); + + private static native void native_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); + +} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_REmbed.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_REmbed.java similarity index 97% rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_REmbed.java rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_REmbed.java index e6fe980732140e280f2c1bfdd4ded4a93d4335f4..bf44eeafa0cc61566f58ebb97d8bfb6340bcdc68 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_REmbed.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_REmbed.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.ffi.jnr; +package com.oracle.truffle.r.runtime.ffi.jni; import com.oracle.truffle.r.runtime.ffi.REmbedRFFI; diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RFFIFactory.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java similarity index 76% rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RFFIFactory.java rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java index da24f27db4ab82bba8840d97541dffae4e408e88..af726e7ecdc27bab43ce06d7f818ef22e304cd1b 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RFFIFactory.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java @@ -20,11 +20,10 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.ffi.jnr; +package com.oracle.truffle.r.runtime.ffi.jni; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.r.runtime.RPlatform; 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; @@ -32,7 +31,7 @@ import com.oracle.truffle.r.runtime.ffi.CRFFI; import com.oracle.truffle.r.runtime.ffi.CallRFFI; 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; import com.oracle.truffle.r.runtime.ffi.PCRERFFI; import com.oracle.truffle.r.runtime.ffi.RApplRFFI; import com.oracle.truffle.r.runtime.ffi.REmbedRFFI; @@ -46,33 +45,17 @@ import com.oracle.truffle.r.runtime.ffi.generic.Generic_Grid; import com.oracle.truffle.r.runtime.ffi.generic.Generic_Tools; /** - * JNR/JNI-based factory. The majority of the FFI instances are instantiated on demand. + * JNI-based factory. The majority of the FFI instances are instantiated on demand. */ -public class JNR_RFFIFactory extends RFFIFactory implements RFFI { +public class JNI_RFFIFactory extends RFFIFactory implements RFFI { - public JNR_RFFIFactory() { + public JNI_RFFIFactory() { } @Override protected void initialize(boolean runtime) { // This must load early as package libraries reference symbols in it. getCallRFFI(); - /* - * Some package C code calls these functions and, therefore, expects the linpack symbols to - * be available, which will not be the case unless one of the functions has already been - * called from R code. So we eagerly load the library to define the symbols. - * - * There is an additional problem when running without a *_LIBRARY_PATH being set which is - * mandated by Mac OSX El Capitan, which is we must tell JNR where to find the libraries. - */ - String jnrLibPath = LibPaths.getBuiltinLibPath(); - if (RPlatform.getOSInfo().osName.equals("Mac OS X")) { - // Why this is necessary is a JNR mystery - jnrLibPath += ":/usr/lib"; - } - System.setProperty("jnr.ffi.library.path", jnrLibPath); - JNR_RAppl.linpack(); - JNR_Lapack.lapack(); } /** @@ -83,7 +66,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI { } @Override - public ContextState newContext(RContext context) { + public ContextState newContextState() { return new ContextStateImpl(); } @@ -98,7 +81,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI { public BaseRFFI getBaseRFFI() { if (baseRFFI == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - baseRFFI = new JNR_Base(); + baseRFFI = new JNI_Base(); } return baseRFFI; } @@ -109,7 +92,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI { public LapackRFFI getLapackRFFI() { if (lapackRFFI == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - lapackRFFI = new JNR_Lapack(); + lapackRFFI = new JNI_Lapack(); } return lapackRFFI; } @@ -120,7 +103,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI { public RApplRFFI getRApplRFFI() { if (rApplRFFI == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - rApplRFFI = new JNR_RAppl(); + rApplRFFI = new JNI_RAppl(); } return rApplRFFI; } @@ -131,7 +114,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI { public StatsRFFI getStatsRFFI() { if (statsRFFI == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - statsRFFI = new JNR_Stats(); + statsRFFI = new JNI_Stats(); } return statsRFFI; } @@ -164,7 +147,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI { public UserRngRFFI getUserRngRFFI() { if (userRngRFFI == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - userRngRFFI = new JNR_UserRng(); + userRngRFFI = new JNI_UserRng(); } return userRngRFFI; } @@ -175,7 +158,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI { public CRFFI getCRFFI() { if (cRFFI == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - cRFFI = new CRFFI_JNR_Invoke(); + cRFFI = new JNI_C(); } return cRFFI; } @@ -186,7 +169,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI { public CallRFFI getCallRFFI() { if (callRFFI == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - callRFFI = new JNI_CallRFFI(); + callRFFI = new JNI_Call(); } return callRFFI; } @@ -197,7 +180,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI { public ZipRFFI getZipRFFI() { if (zipRFFI == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - zipRFFI = new JNR_Zip(); + zipRFFI = new JNI_Zip(); } return zipRFFI; } @@ -207,8 +190,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI { @Override public PCRERFFI getPCRERFFI() { if (pcreRFFI == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - pcreRFFI = new JNR_PCRE(); + pcreRFFI = new JNI_PCRE(); } return pcreRFFI; } @@ -223,4 +205,14 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI { return rEmbedRFFI; } + private MiscRFFI miscRFFI; + + @Override + public MiscRFFI getMiscRFFI() { + if (miscRFFI == null) { + miscRFFI = new JNI_Misc(); + } + return miscRFFI; + } + } diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Stats.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Stats.java similarity index 57% rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Stats.java rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Stats.java index 1f62195064f853ec7e893f5211ad49bf5e23d4cb..460515618e7e8fb6d656cbd9b594f77c4e83df51 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Stats.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Stats.java @@ -20,57 +20,50 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.ffi.jnr; +package com.oracle.truffle.r.runtime.ffi.jni; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.RFFIFactory; import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; import com.oracle.truffle.r.runtime.ffi.StatsRFFI; -import jnr.ffi.LibraryLoader; -import jnr.ffi.annotations.In; -import jnr.ffi.annotations.Out; - // Checkstyle: stop method name -public class JNR_Stats implements StatsRFFI { - public interface Stats { - void fft_factor(int n, @Out int[] pmaxf, @Out int[] pmaxp); +public class JNI_Stats implements StatsRFFI { + @Override + @TruffleBoundary + public void fft_factor(int n, int[] pmaxf, int[] pmaxp) { + native_fft_factor(fft_factor_address(), n, pmaxf, pmaxp); + } - int fft_work(double[] a, int nseg, int n, int nspn, int isn, @In double[] work, @In int[] iwork); + @Override + @TruffleBoundary + public int fft_work(double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork) { + return native_fft_work(fft_work_address(), a, nseg, n, nspn, isn, work, iwork); } - private static class StatsProvider { - private static Stats stats; + private long fft_factor_address; + private long fft_work_address; - @TruffleBoundary - private static Stats createAndLoadLib() { - // fft is in the stats package .so + private long fft_factor_address() { + if (fft_factor_address == 0) { DLLInfo dllInfo = DLL.findLibrary("stats"); - assert dllInfo != null; - return LibraryLoader.create(Stats.class).load(dllInfo.path); - } - - static Stats fft() { - if (stats == null) { - stats = createAndLoadLib(); - } - return stats; + fft_factor_address = RFFIFactory.getRFFI().getBaseRFFI().dlsym(dllInfo.handle, "fft_factor"); + assert fft_factor_address != DLL.SYMBOL_NOT_FOUND; } + return fft_factor_address; } - private static Stats stats() { - return StatsProvider.fft(); + private long fft_work_address() { + if (fft_work_address == 0) { + DLLInfo dllInfo = DLL.findLibrary("stats"); + fft_work_address = RFFIFactory.getRFFI().getBaseRFFI().dlsym(dllInfo.handle, "fft_work"); + assert fft_work_address != DLL.SYMBOL_NOT_FOUND; + } + return fft_work_address; } - @Override - @TruffleBoundary - public void fft_factor(int n, int[] pmaxf, int[] pmaxp) { - stats().fft_factor(n, pmaxf, pmaxp); - } + private static native void native_fft_factor(long address, int n, int[] pmaxf, int[] pmaxp); - @Override - @TruffleBoundary - public int fft_work(double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork) { - return stats().fft_work(a, nseg, n, nspn, isn, work, iwork); - } + private static native int native_fft_work(long address, double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork); } diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java new file mode 100644 index 0000000000000000000000000000000000000000..bc935d7b3223a3002440066511b2252471d85248 --- /dev/null +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java @@ -0,0 +1,62 @@ +/* + * 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.runtime.ffi.jni; + +import static com.oracle.truffle.r.runtime.rng.user.UserRNG.Function; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.runtime.ffi.UserRngRFFI; + +public class JNI_UserRng implements UserRngRFFI { + @Override + @TruffleBoundary + public void init(int seed) { + init(Function.Init.getAddress(), seed); + + } + + @Override + @TruffleBoundary + public double rand() { + return rand(Function.Rand.getAddress()); + } + + @Override + @TruffleBoundary + public int nSeed() { + return nSeed(Function.NSeed.getAddress()); + } + + @Override + @TruffleBoundary + public void seeds(int[] n) { + seeds(Function.Seedloc.getAddress(), n); + } + + private static native void init(long address, int seed); + + private static native double rand(long address); + + private static native int nSeed(long address); + + private static native void seeds(long address, int[] n); +} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_UtsName.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UtsName.java similarity index 97% rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_UtsName.java rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UtsName.java index 5212999dfb9daeecabc1199a122d04f9714a9e20..51151f9636943de72ec687c4303790d86b5cbc48 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_UtsName.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UtsName.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.ffi.jnr; +package com.oracle.truffle.r.runtime.ffi.jni; import com.oracle.truffle.r.runtime.ffi.BaseRFFI.UtsName; diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Zip.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Zip.java similarity index 52% rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Zip.java rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Zip.java index e0de35c38ed459eddb9e7031489d250a929c1f8e..452f10e67820918e49b697d238a416d5597a037d 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Zip.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Zip.java @@ -20,54 +20,33 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.ffi.jnr; +package com.oracle.truffle.r.runtime.ffi.jni; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.ffi.ZipRFFI; -import jnr.ffi.LibraryLoader; -import jnr.ffi.annotations.In; -import jnr.ffi.annotations.Out; - /** - * Zip support using JNR. + * Zip support using JNI. */ -public class JNR_Zip implements ZipRFFI { - public interface Zip { - int compress(@Out byte[] dest, long[] destlen, @In byte[] source, long sourcelen); - - int uncompress(@Out byte[] dest, long[] destlen, @In byte[] source, long sourcelen); - } - - private static class ZipProvider { - private static Zip zip; - - @TruffleBoundary - private static Zip createAndLoadLib() { - return LibraryLoader.create(Zip.class).load("z"); - } - - static Zip zip() { - if (zip == null) { - zip = createAndLoadLib(); - } - return zip; - } - } - - private static Zip zip() { - return ZipProvider.zip(); - } +public class JNI_Zip implements ZipRFFI { @Override @TruffleBoundary - public int compress(byte[] dest, long[] destlen, byte[] source) { - return zip().compress(dest, destlen, source, source.length); + public int compress(byte[] dest, byte[] source) { + int rc = native_compress(dest, dest.length, source, source.length); + return rc; } @Override @TruffleBoundary - public int uncompress(byte[] dest, long[] destlen, byte[] source) { - return zip().uncompress(dest, destlen, source, source.length); + public int uncompress(byte[] dest, byte[] source) { + int rc = native_uncompress(dest, dest.length, source, source.length); + return rc; } + + // Checkstyle: stop method name + + private static native int native_compress(byte[] dest, long destlen, byte[] source, long sourcelen); + + private static native int native_uncompress(byte[] dest, long destlen, byte[] source, long sourcelen); } diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CRFFI_JNR_Invoke.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CRFFI_JNR_Invoke.java deleted file mode 100644 index d5c6fc43c1b1f0edd11fa2fdc6c4c0174cf25953..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CRFFI_JNR_Invoke.java +++ /dev/null @@ -1,71 +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.runtime.ffi.jnr; - -import java.lang.invoke.MethodHandle; - -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.ffi.CRFFI; - -import jnr.invoke.CodeAddress; -import jnr.invoke.DataDirection; -import jnr.invoke.Native; -import jnr.invoke.NativeType; -import jnr.invoke.ParameterType; -import jnr.invoke.ResultType; -import jnr.invoke.Signature; - -/** - * An implementation of {@link CRFFI} that uses {@code jnr-invoke}. - */ -public class CRFFI_JNR_Invoke implements CRFFI { - - /** - * We construct a signature for jnr-invoke based on the types in {@code args}. Everything is an - * array (call by reference for scalars). As we already loaded the library and looked up the - * symbol address we don't need to use JNR for that. - */ - @Override - public void invoke(long address, Object[] args) { - ParameterType[] parameterTypes = new ParameterType[args.length]; - for (int i = 0; i < args.length; i++) { - Object arg = args[i]; - if (arg instanceof double[]) { - parameterTypes[i] = ParameterType.array(double[].class, DataDirection.INOUT); - } else if (arg instanceof int[]) { - parameterTypes[i] = ParameterType.array(int[].class, DataDirection.INOUT); - } else { - assert (false); - } - } - Signature sig = Signature.getSignature(ResultType.primitive(NativeType.VOID, void.class), parameterTypes); - - // We already have up the symbol address - MethodHandle mh = Native.getMethodHandle(sig, new CodeAddress(address)); - try { - mh.invokeWithArguments(args); - } catch (Throwable ex) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, ex.getMessage()); - } - } -} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_OSExtras.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_OSExtras.java deleted file mode 100644 index c903af4de7e6c0a11994f57fec2f74d7f71309e6..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_OSExtras.java +++ /dev/null @@ -1,85 +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.runtime.ffi.jnr; - -import java.util.ArrayList; - -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.ffi.BaseRFFI; -import com.oracle.truffle.r.runtime.ffi.BaseRFFI.UtsName; -import com.oracle.truffle.r.runtime.ffi.LibPaths; - -/** - * Additional support for {@link BaseRFFI} that is implemented using JNI not JNR. - */ -public class JNI_OSExtras { - private interface OSExtras { - UtsName uname(); - - ArrayList<String> glob(String pattern); - } - - private static class OSExtraProvider implements OSExtras { - private static OSExtras osExtras; - - @TruffleBoundary - private static OSExtras createAndLoadLib() { - try { - System.load(LibPaths.getBuiltinLibPath("osextras")); - return new OSExtraProvider(); - } catch (UnsatisfiedLinkError ex) { - throw RInternalError.shouldNotReachHere("osextras"); - } - } - - static OSExtras osExtras() { - if (osExtras == null) { - osExtras = createAndLoadLib(); - } - return osExtras; - } - - @Override - public UtsName uname() { - return JNI_UtsName.get(); - } - - @Override - public ArrayList<String> glob(String pattern) { - return JNI_Glob.glob(pattern); - } - } - - private static OSExtras osExtras() { - return OSExtraProvider.osExtras(); - } - - static UtsName uname() { - return osExtras().uname(); - } - - static ArrayList<String> glob(String pattern) { - return osExtras().glob(pattern); - } -} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Base.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Base.java deleted file mode 100644 index 04dc45199a5dea49b9510e7a7476869669b150cf..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Base.java +++ /dev/null @@ -1,192 +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.runtime.ffi.jnr; - -import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.ioex; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; - -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.r.runtime.ffi.BaseRFFI; - -import jnr.constants.platform.Errno; -import jnr.ffi.LibraryLoader; -import jnr.ffi.annotations.In; -import jnr.ffi.annotations.Out; -import jnr.posix.POSIX; -import jnr.posix.POSIXFactory; - -public class JNR_Base implements BaseRFFI { - /** - * Functions missing from JNR POSIX. - */ - public interface LibCX { - int getwd(@Out byte[] path); - - long mkdtemp(@In @Out ByteBuffer template); - - long strtol(@In String dir, @In String end, int base); - - int uname(@In long[] utsname); - } - - private static class LibCXProvider { - private static LibCX libcx; - - @TruffleBoundary - private static LibCX createAndLoadLib() { - return LibraryLoader.create(LibCX.class).load("c"); - } - - static LibCX libcx() { - if (libcx == null) { - libcx = createAndLoadLib(); - } - return libcx; - } - } - - private static LibCX libcx() { - return LibCXProvider.libcx(); - } - - protected POSIX posix; - - protected POSIX posix() { - if (posix == null) { - posix = POSIXFactory.getPOSIX(); - } - return posix; - } - - @Override - public int getpid() { - return posix().getpid(); - } - - @Override - public int setwd(String dir) { - return posix().chdir(dir); - } - - @Override - public String getwd() { - byte[] buf = new byte[4096]; - int rc = libcx().getwd(buf); - if (rc == 0) { - return null; - } else { - int i = 0; - while (buf[i] != 0 && i < buf.length) { - i++; - } - return new String(buf, 0, i); - } - } - - @Override - public String readlink(String path) throws IOException { - String s = posix().readlink(path); - if (s == null) { - int n = posix().errno(); - if (n == Errno.EINVAL.intValue()) { - // not a link - } else { - // some other error - throw ioex(Errno.valueOf(n).description()); - } - } - return s; - } - - @Override - public String mkdtemp(String template) { - ByteBuffer bb = ByteBuffer.wrap(template.getBytes()); - long result = libcx().mkdtemp(bb); - if (result == 0) { - return null; - } else { - return new String(bb.array()); - } - } - - @Override - public void mkdir(String dir, int mode) throws IOException { - try { - posix().mkdir(dir, mode); - } catch (RuntimeException ex) { - throw ioex(Errno.valueOf(posix().errno()).description()); - } - } - - @Override - public int chmod(String path, int mode) { - return posix().chmod(path, mode); - } - - @Override - public long strtol(String s, int base) throws IllegalArgumentException { - posix().errno(0); - long result = libcx().strtol(s, null, base); - int e = posix().errno(); - if (e != 0) { - throw new IllegalArgumentException(Errno.valueOf(e).description()); - } else { - return result; - } - } - - @Override - public Object dlopen(String path, boolean local, boolean now) { - int flags = (local ? com.kenai.jffi.Library.LOCAL : com.kenai.jffi.Library.GLOBAL) | (now ? com.kenai.jffi.Library.NOW : com.kenai.jffi.Library.LAZY); - return com.kenai.jffi.Library.getCachedInstance(path, flags); - } - - @Override - public long dlsym(Object handle, String symbol) { - return ((com.kenai.jffi.Library) handle).getSymbolAddress(symbol); - } - - @Override - public int dlclose(Object handle) { - // TODO JNR provides no (public) way to close a library - return 1; - } - - @Override - public String dlerror() { - return com.kenai.jffi.Library.getLastError(); - } - - @Override - public UtsName uname() { - return JNI_OSExtras.uname(); - } - - @Override - public ArrayList<String> glob(String pattern) { - return JNI_OSExtras.glob(pattern); - } -} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Lapack.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Lapack.java deleted file mode 100644 index 89ecb117dc52f06dbec05834e7a83754d78bbd1f..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Lapack.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2015, 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.ffi.jnr; - -import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.wrapChar; -import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.wrapDouble; -import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.wrapInt; - -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.r.runtime.ffi.LapackRFFI; - -import jnr.ffi.LibraryLoader; -import jnr.ffi.annotations.In; -import jnr.ffi.annotations.Out; - -public class JNR_Lapack implements LapackRFFI { - /** - * Fortran does call by reference for everything, which we handle with arrays. Evidently, this - * is not as efficient as it could be. This implementation assumes a single-threaded - * environment. - */ - public interface Lapack { - // Checkstyle: stop method name - void ilaver_(@Out int[] major, @Out int[] minor, @Out int[] patch); - - void dgeev_(@In byte[] jobVL, @In byte[] jobVR, @In int[] n, @In double[] a, @In int[] lda, @Out double[] wr, @Out double[] wi, @Out double[] vl, @In int[] ldvl, @Out double[] vr, - @In int[] ldvr, @Out double[] work, @In int[] lwork, @Out int[] info); - - void dgeqp3_(@In int[] m, @In int[] n, double[] a, @In int[] lda, int[] jpvt, @Out double[] tau, @Out double[] work, @In int[] lwork, @Out int[] info); - - void dormqr_(@In byte[] side, @In byte[] trans, @In int[] m, @In int[] n, @In int[] k, @In double[] a, @In int[] lda, @In double[] tau, double[] c, @In int[] ldc, @Out double[] work, - @In int[] lwork, @Out int[] info); - - void dtrtrs_(@In byte[] uplo, @In byte[] trans, @In byte[] diag, @In int[] n, @In int[] nrhs, @In double[] a, @In int[] lda, double[] b, @In int[] ldb, @Out int[] info); - - void dgetrf_(@In int[] m, @In int[] n, double[] a, @In int[] lda, @Out int[] ipiv, @Out int[] info); - - void dpotrf_(@In byte[] uplo, @In int[] n, double[] a, @In int[] lda, @Out int[] info); - - void dpstrf_(@In byte[] uplo, @In int[] n, double[] a, @In int[] lda, @Out int[] piv, @Out int[] rank, @In double[] tol, @Out double[] work, @Out int[] info); - - void dgesv_(@In int[] n, @In int[] nrhs, double[] a, @In int[] lda, @Out int[] ipiv, double[] b, @In int[] ldb, @Out int[] info); - - double dlange_(@In byte[] norm, @In int[] m, @In int[] n, @In double[] a, @In int[] lda, @Out double[] work); - - void dgecon_(@In byte[] norm, @In int[] n, @In double[] a, @In int[] lda, @In double[] anorm, @Out double[] rcond, @Out double[] work, @Out int[] iwork, @Out int[] info); - - } - - private static class LapackProvider { - private static Lapack lapack; - - @TruffleBoundary - private static Lapack createAndLoadLib() { - return LibraryLoader.create(Lapack.class).load("Rlapack"); - } - - static Lapack lapack() { - if (lapack == null) { - lapack = createAndLoadLib(); - } - return lapack; - } - } - - public static Lapack lapack() { - return LapackProvider.lapack(); - } - - @Override - @TruffleBoundary - public void ilaver(int[] version) { - int[] major = new int[1]; - int[] minor = new int[1]; - int[] patch = new int[1]; - lapack().ilaver_(major, minor, patch); - version[0] = major[0]; - version[1] = minor[0]; - version[2] = patch[0]; - } - - @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) { - int[] info = new int[1]; - lapack().dgeev_(wrapChar(jobVL), wrapChar(jobVR), wrapInt(n), a, wrapInt(lda), wr, wi, vl, wrapInt(ldvl), vr, wrapInt(ldvr), work, wrapInt(lwork), info); - return info[0]; - } - - @Override - @TruffleBoundary - public int dgeqp3(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork) { - int[] info = new int[1]; - lapack().dgeqp3_(wrapInt(m), wrapInt(n), a, wrapInt(lda), jpvt, tau, work, wrapInt(lwork), info); - return info[0]; - } - - @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) { - int[] info = new int[1]; - lapack().dormqr_(wrapChar(side), wrapChar(trans), wrapInt(m), wrapInt(n), wrapInt(k), a, wrapInt(lda), tau, c, wrapInt(ldc), work, wrapInt(lwork), info); - return info[0]; - } - - @Override - @TruffleBoundary - public int dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) { - int[] info = new int[1]; - lapack().dtrtrs_(wrapChar(uplo), wrapChar(trans), wrapChar(diag), wrapInt(n), wrapInt(nrhs), a, wrapInt(lda), b, wrapInt(ldb), info); - return info[0]; - } - - @Override - @TruffleBoundary - public int dgetrf(int m, int n, double[] a, int lda, int[] ipiv) { - int[] info = new int[1]; - lapack().dgetrf_(wrapInt(m), wrapInt(n), a, wrapInt(lda), ipiv, info); - return info[0]; - } - - @Override - @TruffleBoundary - public int dpotrf(char uplo, int n, double[] a, int lda) { - int[] info = new int[1]; - lapack().dpotrf_(wrapChar(uplo), wrapInt(n), a, wrapInt(lda), info); - return info[0]; - } - - @Override - @TruffleBoundary - public int dpstrf(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work) { - int[] info = new int[1]; - lapack().dpstrf_(wrapChar(uplo), wrapInt(n), a, wrapInt(lda), piv, rank, wrapDouble(tol), work, info); - return info[0]; - } - - @Override - @TruffleBoundary - public int dgesv(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) { - int[] info = new int[1]; - lapack().dgesv_(wrapInt(n), wrapInt(nrhs), a, wrapInt(lda), ipiv, b, wrapInt(ldb), info); - return info[0]; - } - - @Override - @TruffleBoundary - public double dlange(char norm, int m, int n, double[] a, int lda, double[] work) { - return lapack().dlange_(wrapChar(norm), wrapInt(m), wrapInt(n), a, wrapInt(lda), work); - } - - @Override - @TruffleBoundary - public int dgecon(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork) { - int[] info = new int[1]; - lapack().dgecon_(wrapChar(norm), wrapInt(n), a, wrapInt(lda), wrapDouble(anorm), rcond, work, iwork, info); - return info[0]; - } -} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_PCRE.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_PCRE.java deleted file mode 100644 index 13cae21398ccdcf4a69361c7bad7119f33d8eea3..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_PCRE.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2015, 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.ffi.jnr; - -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.ffi.LibPaths; -import com.oracle.truffle.r.runtime.ffi.PCRERFFI; - -import jnr.ffi.LibraryLoader; -import jnr.ffi.annotations.In; -import jnr.ffi.annotations.Out; - -/** - * PCRE support using JNR. - */ -// Checkstyle: stop method name -public class JNR_PCRE implements PCRERFFI { - public interface PCRE { - long fastr_pcre_maketables(); - - long fastr_pcre_compile(byte[] pattern, int options, @Out byte[] errorMessage, @Out int[] errOffset, long tables); - - int fastr_pcre_exec(long code, long extra, @In byte[] subject, int subjectLength, int startOffset, int options, @Out int[] ovector, int ovecSize); - } - - private static class PCREProvider { - private static PCRE pcre; - - @TruffleBoundary - private static PCRE createAndLoadLib() { - return LibraryLoader.create(PCRE.class).library(LibPaths.getBuiltinLibPath("R")).library("pcre").load(); - } - - static PCRE pcre() { - if (pcre == null) { - pcre = createAndLoadLib(); - } - return pcre; - } - } - - private static PCRE pcre() { - return PCREProvider.pcre(); - } - - @Override - public long maketables() { - return pcre().fastr_pcre_maketables(); - } - - @Override - public Result compile(String pattern, int options, long tables) { - int[] errOffset = new int[1]; - byte[] errorMessage = new byte[512]; - long result = pcre().fastr_pcre_compile(pattern.getBytes(), options, errorMessage, errOffset, tables); - if (result == 0) { - return new Result(result, new String(errorMessage), errOffset[0]); - } else { - return new Result(result, null, 0); - } - } - - @Override - public int exec(long code, long extra, String subject, int offset, int options, int[] ovector) { - return pcre().fastr_pcre_exec(code, extra, subject.getBytes(), subject.length(), offset, options, ovector, ovector.length); - } - - @Override - public Result study(long code, int options) { - throw RInternalError.unimplemented("pcre_study"); - } -} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RAppl.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RAppl.java deleted file mode 100644 index bee80bd631e5f05959bb6fdc30393a0a13a7118f..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RAppl.java +++ /dev/null @@ -1,84 +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.runtime.ffi.jnr; - -import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.wrapDouble; -import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.wrapInt; - -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.r.runtime.ffi.RApplRFFI; - -import jnr.ffi.LibraryLoader; -import jnr.ffi.annotations.In; -import jnr.ffi.annotations.Out; - -//Checkstyle: stop method name -public class JNR_RAppl implements RApplRFFI { - public interface Linpack { - void dqrdc2_(double[] x, @In int[] ldx, @In int[] n, @In int[] p, @In double[] tol, int[] rank, double[] qraux, int[] pivot, @Out double[] work); - - void dqrcf_(double[] x, @In int[] n, @In int[] k, double[] qraux, double[] y, @In int[] ny, double[] b, int[] info); - - void dqrls_(double[] x, @In int[] n, @In int[] p, @In double[] y, @In int[] ny, @In double[] tol, @Out double[] b, @Out double[] rsd, @Out double[] qty, @Out int[] k, int[] jpvt, - @Out double[] qraux, @In double[] work); - } - - private static class LinpackProvider { - private static Linpack linpack; - - @TruffleBoundary - private static Linpack createAndLoadLib() { - // need to load blas lib as Fortran functions in appl lib need it - return LibraryLoader.create(Linpack.class).library("Rblas").library("R").load(); - } - - static Linpack linpack() { - if (linpack == null) { - linpack = createAndLoadLib(); - } - return linpack; - } - } - - public static Linpack linpack() { - return LinpackProvider.linpack(); - } - - @Override - @TruffleBoundary - public void dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work) { - linpack().dqrdc2_(x, wrapInt(ldx), wrapInt(n), wrapInt(p), wrapDouble(tol), rank, qraux, pivot, work); - } - - @Override - @TruffleBoundary - public void dqrcf(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info) { - linpack().dqrcf_(x, wrapInt(n), wrapInt(k), qraux, y, wrapInt(ny), b, info); - } - - @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) { - linpack().dqrls_(x, wrapInt(n), wrapInt(p), y, wrapInt(ny), wrapDouble(tol), b, rsd, qty, k, jpvt, qraux, work); - } -} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_UserRng.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_UserRng.java deleted file mode 100644 index ff50fa1416cd3935c2afbe2f0b9915aeb257a3db..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_UserRng.java +++ /dev/null @@ -1,103 +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.runtime.ffi.jnr; - -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.r.runtime.ffi.UserRngRFFI; - -import jnr.ffi.LibraryLoader; -import jnr.ffi.Pointer; -import jnr.ffi.annotations.In; - -//Checkstyle: stop method name -public class JNR_UserRng implements UserRngRFFI { - public interface UserRng { - void user_unif_init(@In int seed); - - Pointer user_unif_rand(); - - Pointer user_unif_nseed(); - - Pointer user_unif_seedloc(); - } - - private static class UserRngProvider { - private static String libPath; - private static UserRng userRng; - - UserRngProvider(String libPath) { - UserRngProvider.libPath = libPath; - } - - @TruffleBoundary - private static UserRng createAndLoadLib() { - return LibraryLoader.create(UserRng.class).load(libPath); - } - - static UserRng userRng() { - if (userRng == null) { - userRng = createAndLoadLib(); - } - return userRng; - } - } - - private static UserRng userRng() { - return UserRngProvider.userRng(); - } - - @Override - @SuppressWarnings("unused") - public void setLibrary(String path) { - new UserRngProvider(path); - - } - - @Override - @TruffleBoundary - public void init(int seed) { - userRng().user_unif_init(seed); - } - - @Override - @TruffleBoundary - public double rand() { - Pointer pDouble = userRng().user_unif_rand(); - return pDouble.getDouble(0); - } - - @Override - @TruffleBoundary - public int nSeed() { - return userRng().user_unif_nseed().getInt(0); - } - - @Override - @TruffleBoundary - public void seeds(int[] n) { - Pointer pInt = userRng().user_unif_seedloc(); - for (int i = 0; i < n.length; i++) { - n[i] = pInt.getInt(i * 4); - } - } -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java index 9132ef16228f3fa65e5b00ad550e40a32032a94e..7c3def09aa07d436b25b8cdbfdc7a4c5f13bff1a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java @@ -46,8 +46,6 @@ public final class ArgumentsSignature implements Iterable<String> { public static final String VARARG_NAME = "..."; public static final int NO_VARARG = -1; - private static final String VARARG_GETTER_PREFIX = ".."; - @CompilationFinal private static final ArgumentsSignature[] EMPTY_SIGNATURES = new ArgumentsSignature[32]; public static final ArgumentsSignature INVALID_SIGNATURE = new ArgumentsSignature(new String[]{"<<invalid>>"}); @@ -78,7 +76,7 @@ public final class ArgumentsSignature implements Iterable<String> { @CompilationFinal private final String[] names; @CompilationFinal private final int[] varArgIndexes; @CompilationFinal private final boolean[] isVarArg; - @CompilationFinal private final boolean[] isVarArgGetter; + private final int varArgIndex; private final int nonNullCount; private ArgumentsSignature(String[] names) { @@ -88,7 +86,6 @@ public final class ArgumentsSignature implements Iterable<String> { int index = NO_VARARG; int count = 0; this.isVarArg = new boolean[names.length]; - this.isVarArgGetter = new boolean[names.length]; for (int i = 0; i < names.length; i++) { String name = names[i]; if (name != null) { @@ -98,8 +95,6 @@ public final class ArgumentsSignature implements Iterable<String> { if (index != NO_VARARG) { index = i; } - } else if (name.startsWith(VARARG_GETTER_PREFIX)) { - this.isVarArgGetter[i] = true; } } } @@ -110,6 +105,7 @@ public final class ArgumentsSignature implements Iterable<String> { varArgIndexes[pos++] = i; } } + this.varArgIndex = varArgIndexes.length == 0 ? NO_VARARG : varArgIndexes[0]; } public boolean isEmpty() { @@ -126,7 +122,7 @@ public final class ArgumentsSignature implements Iterable<String> { public int getVarArgIndex() { assert varArgIndexes.length <= 1 : "cannot ask for _the_ vararg index if there are multiple varargs"; - return varArgIndexes.length == 0 ? NO_VARARG : varArgIndexes[0]; + return varArgIndex; } public int getVarArgCount() { @@ -207,7 +203,7 @@ public final class ArgumentsSignature implements Iterable<String> { * methods {@link #isVarArgsIndex(long)}, {@link #extractVarArgsArgumentIndex(long)} and * {@link #extractVarArgsArgumentIndex(long)} to access the data packed in the {@code long} * value. This method also removes arguments that are marked as 'unmatched' in the signature. - * + * * @param argListSize length of the result -- sum of lengths of all varargs contained within * varArgSignatures minus any unmatched arguments. */ 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 fb9aadcd68888f2d52dfbf0cbf6ddc9437b65fbd..ad6c96a2c8b6214b98759ee31d80f62a2d8e534a 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 @@ -25,6 +25,7 @@ package com.oracle.truffle.r.runtime; import java.util.Map; import java.util.Map.Entry; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; /** @@ -43,13 +44,11 @@ public enum FastROptions { TraceCalls("Trace all R function calls", false), TraceCallsToFile("TraceCalls output is sent to 'fastr_tracecalls.log'", false), TraceNativeCalls("Trace all native function calls (performed via .Call, .External, etc.)", false), - PerfStats("PerfStats=p1,p2,...; Collect performance stats identified by p1, etc.", null, true), - PerfStatsFile("PerfStatsFile=file; Send performance stats to 'file', default stdout", null, true), 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), PrintComplexLookups("Print a message for each non-trivial variable lookup", false), - IgnoreVisibility("Ignore setting of the visibility flag", false), + FullPrecisionSum("Use 128 bit arithmetic in sum builtin", false), LoadPkgSourcesIndex("Load R package sources index", true), InvisibleArgs("Argument writes do not trigger state transitions", true), RefCountIncrementOnly("Disable reference count decrements for experimental state transition implementation", false), @@ -84,6 +83,7 @@ public enum FastROptions { if (value instanceof Boolean) { return (Boolean) value; } else { + CompilerDirectives.transferToInterpreter(); System.out.println("boolean option value expected with " + name() + " - forgot +/- ?"); System.exit(2); return false; @@ -96,6 +96,7 @@ public enum FastROptions { if (value == null || value instanceof String) { return (String) value; } else { + CompilerDirectives.transferToInterpreter(); System.out.println("string option value expected with " + name()); System.exit(2); return ""; @@ -104,10 +105,15 @@ public enum FastROptions { public int getNonNegativeIntValue() { assert !isBoolean; + if (value instanceof Integer) { + return (Integer) value; + } + CompilerDirectives.transferToInterpreterAndInvalidate(); if (value instanceof String) { try { int res = Integer.decode((String) value); if (res >= 0) { + value = res; return res; } // else fall through to error message } catch (NumberFormatException x) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyDBCache.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyDBCache.java index ab4b19c7e04187feceb1d8cc9126307e2b2611f3..6b742edcf91819f1db05231372d374d31af946cf 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyDBCache.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyDBCache.java @@ -54,7 +54,7 @@ public class LazyDBCache { dbCache.remove(dbPath); } - public static ContextStateImpl newContext(@SuppressWarnings("unused") RContext context) { + public static ContextStateImpl newContextState() { return new ContextStateImpl(); } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ProcessOutputManager.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ProcessOutputManager.java index 3297270699a952daaebdb5c2746b7448f90adb54..84a01016a8ebc87fc3a9918e4ab3f8246e607d64 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ProcessOutputManager.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ProcessOutputManager.java @@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime; import java.io.IOException; import java.io.InputStream; +import java.util.concurrent.Semaphore; /** * Managing output from sub-processes, which is needed in a several places, e.g. @@ -33,6 +34,8 @@ public class ProcessOutputManager { public abstract static class OutputThread extends Thread { protected final InputStream is; protected int totalRead; + protected final Semaphore entry = new Semaphore(0); + protected final Semaphore exit = new Semaphore(0); protected OutputThread(String name, InputStream is) { super(name); @@ -93,16 +96,23 @@ public class ProcessOutputManager { } } } catch (IOException ex) { - return; + // unexpected, we will just return what we have read so far + } finally { + exit.release(); } } /** - * Returns the internal byte array used to store the data, which may be larger than - * {@link #totalRead}. Use {@link #getTotalRead} to access the subarray containg the read - * data. + * Waits for the reads to complete and then returns the internal byte array used to store + * the data, which may be larger than {@link #totalRead}. Use {@link #getTotalRead} to + * access the subarray containing the read data. */ public byte[] getData() { + try { + exit.acquire(); + } catch (InterruptedException e) { + + } return data; } } 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 35ebce4aa43a83817be26942121d23bc3a2fbe36..6fe38d5db1bb7f8b3abb758119d0cefe9e471198 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 @@ -169,18 +169,10 @@ public final class RArguments { return frame.getArguments().length - INDEX_ARGUMENTS; } - public static Object[] create(RFunction functionObj, RCaller call, MaterializedFrame callerFrame, Object[] evaluatedArgs, DispatchArgs dispatchArgs) { - ArgumentsSignature formalSignature = ((HasSignature) functionObj.getRootNode()).getSignature(); - return create(functionObj, call, callerFrame, evaluatedArgs, ArgumentsSignature.empty(formalSignature.getLength()), dispatchArgs); - } - - public static Object[] create(RFunction functionObj, RCaller call, MaterializedFrame callerFrame, Object[] evaluatedArgs, ArgumentsSignature suppliedSignature, DispatchArgs dispatchArgs) { + public static Object[] create(RFunction function, RCaller call, MaterializedFrame callerFrame, Object[] evaluatedArgs, DispatchArgs dispatchArgs) { + ArgumentsSignature formalSignature = ((HasSignature) function.getRootNode()).getSignature(); CompilerAsserts.neverPartOfCompilation(); - return create(functionObj, call, callerFrame, evaluatedArgs, suppliedSignature, functionObj.getEnclosingFrame(), dispatchArgs); - } - - public static Object[] create(RFunction functionObj, RCaller call, MaterializedFrame callerFrame, Object[] evaluatedArgs, MaterializedFrame enclosingFrame, DispatchArgs dispatchArgs) { - return create(functionObj, call, callerFrame, evaluatedArgs, ArgumentsSignature.empty(evaluatedArgs.length), enclosingFrame, dispatchArgs); + return create(function, call, callerFrame, evaluatedArgs, ArgumentsSignature.empty(formalSignature.getLength()), function.getEnclosingFrame(), dispatchArgs); } /** @@ -194,7 +186,7 @@ public final class RArguments { * function as well as additional information like the parent frame or supplied * signature. */ - public static Object[] create(RFunction functionObj, RCaller call, MaterializedFrame callerFrame, Object[] evaluatedArgs, + public static Object[] create(RFunction function, RCaller call, MaterializedFrame callerFrame, Object[] evaluatedArgs, ArgumentsSignature suppliedSignature, MaterializedFrame enclosingFrame, DispatchArgs dispatchArgs) { assert suppliedSignature.getLength() == evaluatedArgs.length : "suppliedSignature should match the evaluatedArgs (see Java docs)."; assert evaluatedArgs != null : "RArguments.create evaluatedArgs is null"; @@ -204,7 +196,7 @@ public final class RArguments { Object[] a = new Object[MINIMAL_ARRAY_LENGTH + evaluatedArgs.length]; a[INDEX_ENVIRONMENT] = null; - a[INDEX_FUNCTION] = functionObj; + a[INDEX_FUNCTION] = function; a[INDEX_CALL] = call; a[INDEX_CALLER_FRAME] = callerFrame; a[INDEX_ENCLOSING_FRAME] = enclosingFrame; @@ -308,11 +300,6 @@ public final class RArguments { frame.getArguments()[INDEX_IS_IRREGULAR] = isIrregularFrame; } - public static void setIsIrregular(Object[] arguments, boolean isIrregularFrame) { - assert arguments.length >= INDEX_ARGUMENTS; - arguments[INDEX_IS_IRREGULAR] = isIrregularFrame; - } - public static void setEnclosingFrame(Frame frame, MaterializedFrame newEnclosingFrame) { CompilerAsserts.neverPartOfCompilation(); Object[] arguments = frame.getArguments(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.java index a8dd3a444a1376e122400b57b0f2698e5a64728f..d24866761216019787a11b85552a225121c926c2 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.java @@ -33,9 +33,12 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; */ public final class RCaller { + public static final RCaller topLevel = RCaller.createInvalid(null); + private static final Object PROMISE_MARKER = new Object(); private final int depth; + private boolean visibility; private final RCaller parent; /** * payload can be an RSyntaxNode, a {@link Supplier}, or an PROMISE_MARKER. @@ -96,6 +99,11 @@ public final class RCaller { return new RCaller(callingFrame, node); } + public static RCaller create(Frame callingFrame, RCaller parent, RSyntaxNode node) { + assert node != null; + return new RCaller(depthFromFrame(callingFrame), parent, node); + } + public static RCaller create(Frame callingFrame, Supplier<RSyntaxNode> supplier) { assert supplier != null; return new RCaller(callingFrame, supplier); @@ -109,4 +117,12 @@ public final class RCaller { public static RCaller createForPromise(RCaller original, int newDepth) { return new RCaller(newDepth, original, PROMISE_MARKER); } + + public boolean getVisibility() { + return visibility; + } + + public void setVisibility(boolean visibility) { + this.visibility = visibility; + } } 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 d537893caf75a3d2f07d1524621af4597071ea0f..0fec763e0e56036ee7fb48ae964ffcfafebab476 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 @@ -23,21 +23,33 @@ package com.oracle.truffle.r.runtime; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Semaphore; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.source.Source; import com.oracle.truffle.r.runtime.conn.RConnection; +import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RAttributeStorage; import com.oracle.truffle.r.runtime.data.RAttributes; import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; +import com.oracle.truffle.r.runtime.data.RDataFactory; +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.RList; +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.RShareable; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.RUnboundValue; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.REnvTruffleFrameAccess; +import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; /** * Implementation of a channel abstraction used for communication between parallel contexts in @@ -157,248 +169,539 @@ public class RChannel { } } - private static class SerializedList { - - private RList list; + public static void send(int id, Object data) { + Output out = new Output(); + Object msg = out.processOutgoingMessage(data); + RChannel channel = getChannelFromId(id); + try { + (id > 0 ? channel.masterToClient : channel.clientToMaster).put(msg); + } catch (InterruptedException x) { + throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error sending through the channel"); + } + } - SerializedList(RList list) { - this.list = list; + public static Object receive(int id) { + RChannel channel = getChannelFromId(id); + try { + Object msg = (id < 0 ? channel.masterToClient : channel.clientToMaster).take(); + Input in = new Input(); + return in.processedReceivedMessage(msg); + } catch (InterruptedException x) { + throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error receiving from the channel"); } + } - public RList getList() { - return list; + public static Object poll(int id) { + RChannel channel = getChannelFromId(id); + Object msg = (id < 0 ? channel.masterToClient : channel.clientToMaster).poll(); + if (msg != null) { + Input in = new Input(); + return in.processedReceivedMessage(msg); } + return null; } - private static void makeShared(Object o) { - if (o instanceof RShareable) { - RShareable shareable = (RShareable) o; - shareable.makeSharedPermanent(); + private static class TransmitterCommon extends RSerialize.RefCounter { + + protected static class SerializedRef { + private final int index; + + public SerializedRef(int index) { + this.index = index; + } + + public int getIndex() { + return index; + } + } + + protected static class SerializedList { + + private final RList list; + + SerializedList(RList list) { + this.list = list; + } + + public RList getList() { + return list; + } + } + + protected static class SerializedEnv { + + public static class Bindings { + private final String[] names; + private final Object[] values; + + Bindings(String[] names, Object[] values) { + this.names = names; + this.values = values; + } + } + + private Bindings bindings; + // parent can be SerializedEnv or byte[] + private Object parent; + private RAttributes attributes; + + SerializedEnv(Bindings bindings, Object parent, RAttributes attributes) { + this.bindings = bindings; + this.parent = parent; + this.attributes = attributes; + } + + public String[] getNames() { + return bindings.names; + } + + public Object[] getValues() { + return bindings.values; + } + + public Object getParent() { + return parent; + } + + public RAttributes getAttributes() { + return attributes; + } + } + + protected static class SerializedPromise { + + private final Object env; + private final Object value; + private final byte[] serializedExpr; + + public SerializedPromise(Object env, Object value, byte[] serializedExpr) { + this.env = env; + this.value = value; + this.serializedExpr = serializedExpr; + } + + public Object getEnv() { + return env; + } + + public Object getValue() { + return value; + } + + public byte[] getSerializedExpr() { + return serializedExpr; + } + + } + + protected static class SerializedFunction { + private final RAttributes attributes; + private final Object env; + private final byte[] serializedDef; + + public SerializedFunction(RAttributes attributes, Object env, byte[] serializedDef) { + this.attributes = attributes; + this.env = env; + this.serializedDef = serializedDef; + } + + public RAttributes getAttributes() { + return attributes; + } + + public Object getEnv() { + return env; + } + + public byte[] getSerializedDef() { + return serializedDef; + } + } + + protected static class SerializedAttributable { + + private final RAttributes attributes; + private final byte[] serializedAttributable; + + public SerializedAttributable(RAttributes attributes, byte[] serializedAttributable) { + this.attributes = attributes; + this.serializedAttributable = serializedAttributable; + } + + public RAttributes getAttributes() { + return attributes; + } + + public byte[] getSerializedAttributable() { + return serializedAttributable; + } + } } - @TruffleBoundary - private static Object convertListAttributesToPrivate(RList l, Object shareableList) throws IOException { - RAttributes attr = l.getAttributes(); - RAttributes newAttr = createShareableSlow(attr); - if (newAttr != attr) { - RList newList; - if (shareableList == l) { - // need to create a copy due to different attributes - newList = (RList) l.copy(); + private static class Output extends TransmitterCommon { + + private static Object makeShared(Object o) { + if (o instanceof RShareable) { + RShareable shareable = (RShareable) o; + shareable.makeSharedPermanent(); + } + return o; + } + + @TruffleBoundary + private Object convertListAttributesToPrivate(RList l, Object shareableList) throws IOException { + RAttributes attr = l.getAttributes(); + RAttributes newAttr = createShareableSlow(attr, false); + if (newAttr != attr) { + RList newList; + if (shareableList == l) { + // need to create a copy due to different attributes + newList = (RList) l.copy(); + } else { + newList = ((SerializedList) shareableList).getList(); + } + // it's OK to use initAttributes() as the shape of the list (that + // could have otherwise been modified by setting attributes, such as dim + // attribute) is already set correctly by the copy operation + newList.initAttributes(newAttr); + return newList; } else { - newList = ((SerializedList) shareableList).getList(); + if (shareableList != l) { + // shareableList is "fresh" (not shared) and needs its own attribute object + ((SerializedList) shareableList).getList().initAttributes(newAttr); + } // else list and attribute objects haven't changed + return shareableList; } - // it's OK to use initAttributes() as the shape of the list (that - // could have otherwise been modified by setting attributes, such as dim - // attribute) is already set correctly by the copy operation - newList.initAttributes(newAttr); - return newList; - } else { - // shareable attributes are the same - no need for any changes - return shareableList; } - } - @TruffleBoundary - private static Object convertObjectAttributesToPrivate(Object msg) throws IOException { - RAttributable attributable = (RAttributable) msg; - RAttributes attr = attributable.getAttributes(); - RAttributes newAttr = createShareableSlow(attr); - if (attributable instanceof RAbstractVector) { - attributable = ((RAbstractVector) msg).copy(); - } - // see convertListAttributesToPrivate() why it is OK to use initAttributes() here - attributable.initAttributes(newAttr); - return attributable; - } + @TruffleBoundary + private Object convertObjectAttributesToPrivate(Object msg) throws IOException { + RAttributable attributable = (RAttributable) msg; + RAttributes attr = attributable.getAttributes(); + RAttributes newAttr = createShareableSlow(attr, false); + if (newAttr != attr && attributable instanceof RShareable) { + attributable = (RAttributable) ((RShareable) msg).copy(); + } + // see convertListAttributesToPrivate() why it is OK to use initAttributes() here + attributable.initAttributes(newAttr); + return attributable; + } - private static Object convertPrivateList(Object msg) throws IOException { - RList l = (RList) msg; - Object newMsg = createShareable(l); - if (l.getAttributes() != null) { - return convertListAttributesToPrivate(l, newMsg); - } else { - return newMsg; + private Object convertPrivateList(Object msg) throws IOException { + RList l = (RList) msg; + Object newMsg = createShareable(l); + if (l.getAttributes() != null) { + return convertListAttributesToPrivate(l, newMsg); + } else { + return newMsg; + } } - } - private static boolean serializeObject(Object o) { - return o instanceof RFunction || o instanceof REnvironment || o instanceof RConnection || o instanceof RLanguage || o instanceof RPromise; - } + private Object convertPrivateEnv(Object msg) throws IOException { + int refInd = getRefIndex(msg); + if (refInd != -1) { + return new SerializedRef(refInd); + } else { + addReadRef(msg); + } + REnvironment env = (REnvironment) msg; + RAttributes attributes = env.getAttributes(); + if (attributes != null) { + attributes = createShareableSlow(attributes, true); + } + SerializedEnv.Bindings bindings = createShareable(env); - private static Object convertPrivate(Object o) throws IOException { - if (o instanceof RList) { - return convertPrivateList(o); - } else if (!serializeObject(o)) { - // we need to make internal values (permanently) shared to avoid updates to ref count - // by different threads - makeShared(o); - if (o instanceof RAttributable && ((RAttributable) o).getAttributes() != null) { - return convertObjectAttributesToPrivate(o); + return new SerializedEnv(bindings, convertPrivateSlow(env.getParent()), attributes); + } + + private SerializedPromise convertPrivatePromise(Object msg) throws IOException { + RPromise p = (RPromise) msg; + byte[] serializedPromiseRep = RSerialize.serializePromiseRep(p); + if (p.isEvaluated()) { + return new SerializedPromise(RNull.instance, p.getValue(), serializedPromiseRep); } else { - return o; + REnvironment env = p.getFrame() == null ? REnvironment.globalEnv() : REnvironment.frameToEnvironment(p.getFrame()); + return new SerializedPromise(convertPrivate(env), RUnboundValue.instance, serializedPromiseRep); } - } else { - return RSerialize.serialize(o, RSerialize.XDR, RSerialize.DEFAULT_VERSION, null); + + } + + private SerializedFunction convertPrivateFunction(Object msg) throws IOException { + RFunction fn = (RFunction) msg; + byte[] serializedFunctionDef = RSerialize.serializeFunctionNonEnv(fn); + Object env = convertPrivate(REnvironment.frameToEnvironment(fn.getEnclosingFrame())); + RAttributes attributes = fn.getAttributes(); + return new SerializedFunction(attributes == null ? null : createShareableSlow(attributes, true), env, serializedFunctionDef); } - } - private static Object createShareable(RList list) throws IOException { - RList newList = list; - for (int i = 0; i < list.getLength(); i++) { - Object el = list.getDataAt(i); - Object newEl = convertPrivate(el); - if (el != newEl) { - // conversion happened update element - if (list == newList) { - // create a shallow copy - newList = (RList) list.copy(); + private Object convertPrivateAttributable(Object msg) throws IOException { + // do full serialization but handle attributes separately (no reason to serialize them + // unconditionally) + RAttributable attributable = (RAttributable) msg; + RAttributes attributes = attributable.getAttributes(); + if (attributes != null) { + assert attributable instanceof RAttributeStorage; + // TODO: we assume that the following call will reset attributes without clearing + // them - should we define a new method to be used here? + attributable.initAttributes(null); + } + byte[] serializedAttributable = RSerialize.serialize(attributable, RSerialize.XDR, RSerialize.DEFAULT_VERSION, null); + if (attributes != null) { + attributable.initAttributes(attributes); + attributes = createShareableSlow(attributes, true); + } + return new SerializedAttributable(attributes, serializedAttributable); + } + + private static boolean shareableEnv(Object o) { + if (o instanceof REnvironment) { + REnvironment env = (REnvironment) o; + if (env == REnvironment.emptyEnv() || env == REnvironment.baseEnv() || env == REnvironment.globalEnv() || env == REnvironment.baseNamespaceEnv() || env.isPackageEnv() != null || + env.isNamespaceEnv()) { + return false; + } else { + return true; } - newList.updateDataAt(i, newEl, null); + } else { + return false; } } - return list == newList ? list : new SerializedList(newList); - } - /* - * To break recursion within Truffle boundary - */ - @TruffleBoundary - private static Object createShareableSlow(RList list) throws IOException { - return createShareable(list); - } + private static boolean serializeObject(Object o) { + return o instanceof REnvironment || o instanceof RConnection || o instanceof RLanguage; + } - @TruffleBoundary - private static RAttributes createShareableSlow(RAttributes attr) throws IOException { - RAttributes newAttr = attr; - for (RAttribute a : attr) { - Object val = a.getValue(); - Object newVal = convertPrivate(val); - if (val != newVal) { - // conversion happened update element - if (attr == newAttr) { - // create a shallow copy - newAttr = attr.copy(); + private Object convertPrivate(Object o) throws IOException { + if (o instanceof RList) { + return convertPrivateListSlow(o); + } else if (shareableEnv(o)) { + return convertPrivateEnv(o); + } else if (o instanceof RPromise) { + return convertPrivatePromise(o); + } else if (o instanceof RFunction) { + return convertPrivateFunction(o); + } else if (!serializeObject(o)) { + // we need to make internal values (permanently) shared to avoid updates to ref + // count by different threads + if (o instanceof RAttributable && ((RAttributable) o).getAttributes() != null) { + Object newObj = convertObjectAttributesToPrivate(o); + if (newObj == o) { + makeShared(o); + } // otherwise a copy has been created to store new attributes + return newObj; + } else { + return makeShared(o); } - newAttr.put(a.getName(), newVal); + } else { + assert o instanceof RAttributable; + return convertPrivateAttributable(o); } } - return newAttr; - } + private Object createShareable(RList list) throws IOException { + RList newList = list; + for (int i = 0; i < list.getLength(); i++) { + Object el = list.getDataAt(i); + Object newEl = convertPrivate(el); + if (el != newEl) { + // conversion happened update element + if (list == newList) { + // create a shallow copy + newList = (RList) list.copy(); + } + newList.updateDataAt(i, newEl, null); + } + } + return list == newList ? makeShared(list) : new SerializedList(newList); + } - public static void send(int id, Object data) { - Object msg = data; - RChannel channel = getChannelFromId(id); - if (msg instanceof RList) { + @TruffleBoundary + private SerializedEnv.Bindings createShareable(REnvironment e) throws IOException { + String[] names = REnvTruffleFrameAccess.getStringIdentifiers(e.getFrame().getFrameDescriptor()); + Object[] values = new Object[names.length]; + int ind = 0; + for (String n : names) { + values[ind++] = convertPrivate(e.get(n)); + } + return new SerializedEnv.Bindings(names, values); + } + + /* + * To break recursion within Truffle boundary + */ + @TruffleBoundary + private Object convertPrivateSlow(Object o) throws IOException { + return convertPrivate(o); + } + + @TruffleBoundary + private Object convertPrivateListSlow(Object msg) throws IOException { + return convertPrivateList(msg); + } + + @TruffleBoundary + private RAttributes createShareableSlow(RAttributes attr, boolean forceCopy) throws IOException { + RAttributes newAttr = forceCopy ? RAttributes.create(attr) : attr; + for (RAttribute a : attr) { + Object val = a.getValue(); + Object newVal = convertPrivate(val); + if (val != newVal) { + // conversion happened update element + if (attr == newAttr && !forceCopy) { + // create a shallow copy if not already created + newAttr = attr.copy(); + } + newAttr.put(a.getName(), newVal); + } + } + + return newAttr; + } + + public Object processOutgoingMessage(Object data) { try { - msg = convertPrivateList(msg); + return convertPrivate(data); } catch (IOException x) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error creating shareable list"); + throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error serializing message for channel transmission"); } - } else if (!serializeObject(msg)) { - // make sure that what's passed through the channel will be copied on the first - // update - makeShared(msg); - try { - if (msg instanceof RAttributable && ((RAttributable) msg).getAttributes() != null) { - msg = convertObjectAttributesToPrivate(msg); + } + + } + + private static class Input extends TransmitterCommon { + + private Object unserializeObject(Object el) throws IOException { + Object ret = el; + if (el instanceof SerializedRef) { + ret = getReadRef(((SerializedRef) el).getIndex()); + } else { + if (el instanceof SerializedList) { + RList elList = ((SerializedList) el).getList(); + unserializeListSlow(elList); + ret = elList; + } else if (el instanceof SerializedEnv) { + ret = unserializeEnv((SerializedEnv) el); + } else if (el instanceof SerializedPromise) { + ret = unserializePromise((SerializedPromise) el); + } else if (el instanceof SerializedFunction) { + ret = unserializeFunction((SerializedFunction) el); + } else if (el instanceof SerializedAttributable) { + ret = unserializeAttributable((SerializedAttributable) el); + } + if (ret instanceof RAttributable && ((RAttributable) ret).getAttributes() != null) { + unserializeAttributes((RAttributable) ret); } - } catch (IOException x) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error creating channel message"); } - } else { - msg = RSerialize.serialize(msg, RSerialize.XDR, RSerialize.DEFAULT_VERSION, null); + return ret; } - try { - (id > 0 ? channel.masterToClient : channel.clientToMaster).put(msg); - } catch (InterruptedException x) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error sending through the channel"); + + private void unserializeList(RList list) throws IOException { + for (int i = 0; i < list.getLength(); i++) { + Object el = list.getDataAt(i); + Object newEl = unserializeObject(el); + if (newEl != el) { + list.updateDataAt(i, newEl, null); + } + } } - } - private static Object unserializeObject(Object el) throws IOException { - Object ret; - if (el instanceof SerializedList) { - RList elList = ((SerializedList) el).getList(); - unserializeList(elList); - ret = elList; - } else if (el instanceof byte[]) { - ret = RSerialize.unserialize((byte[]) el, null, null, null); - } else { - ret = el; - } - if (ret instanceof RAttributable && ((RAttributable) ret).getAttributes() != null) { - unserializeAttributes(((RAttributable) ret).getAttributes()); - } - return ret; - } + @TruffleBoundary + private REnvironment unserializeEnv(SerializedEnv e) throws IOException { + Object[] values = e.getValues(); + String[] names = e.getNames(); + assert values.length == names.length; + REnvironment.NewEnv env = RDataFactory.createNewEnv(null); + addReadRef(env); + int ind = 0; + for (String n : names) { + Object newValue = unserializeObject(values[ind++]); + env.safePut(n, newValue); + } + REnvironment parent = (REnvironment) unserializeObject(e.getParent()); + RArguments.initializeEnclosingFrame(env.getFrame(), parent.getFrame()); + RAttributes attributes = e.getAttributes(); + if (attributes != null) { + env.initAttributes(attributes); + } + return env; + } - @TruffleBoundary - private static void unserializeList(RList list) throws IOException { - for (int i = 0; i < list.getLength(); i++) { - Object el = list.getDataAt(i); - Object newEl = unserializeObject(el); - if (newEl != el) { - list.updateDataAt(i, newEl, null); + @TruffleBoundary + private RPromise unserializePromise(SerializedPromise p) throws IOException { + Map<String, Object> constants = new HashMap<>(); + String deparse = RDeparse.deparseDeserialize(constants, RSerialize.unserialize(p.getSerializedExpr(), null, null, null)); + Source source = RSource.fromPackageTextInternal(deparse, null); + RExpression expr = RContext.getEngine().parse(constants, source); + Object env = p.getEnv(); + if (env != RNull.instance) { + env = unserializeObject(env); } + return RSerialize.unserializePromise(expr, env, p.getValue()); } - } - @TruffleBoundary - private static void unserializeAttributes(RAttributes attr) throws IOException { - for (RAttribute a : attr) { - Object val = a.getValue(); - Object newVal = unserializeObject(val); - if (newVal != val) { - // TODO: this is a bit brittle as it relies on the iterator to work correctly in the - // face of updates (which it does under current implementation of attributes) - attr.put(a.getName(), newVal); + @TruffleBoundary + private RFunction unserializeFunction(SerializedFunction f) throws IOException { + Map<String, Object> constants = new HashMap<>(); + RPairList l = (RPairList) RSerialize.unserialize(f.getSerializedDef(), null, null, null); + // seems like the best (only) way to make deparser see a correct pair list type here + RPairList closxpList = RDataFactory.createPairList(l.car(), l.cdr(), RNull.instance, SEXPTYPE.CLOSXP); + String deparse = RDeparse.deparseDeserialize(constants, closxpList); + REnvironment env = (REnvironment) unserializeObject(f.getEnv()); + MaterializedFrame enclosingFrame = env.getFrame(); + RFunction fn = RContext.getEngine().parseFunction(constants, null, RSource.fromTextInternal(deparse, RSource.Internal.PAIRLIST_DEPARSE), enclosingFrame); + RAttributes attributes = f.getAttributes(); + if (attributes != null) { + assert fn.getAttributes() == null; + // attributes unserialized in caller methods + fn.initAttributes(attributes); } + return fn; } - } - private static Object processedReceivedMessage(Object msg) { - try { - if (msg instanceof SerializedList) { - RList list = ((SerializedList) msg).getList(); - // list and attributes are already private (shallow copies - do the appropriate - // changes in place) - unserializeList(list); - if (list.getAttributes() != null) { - unserializeAttributes(list.getAttributes()); - } - return list; - } else if (msg instanceof byte[]) { - return RSerialize.unserialize((byte[]) msg, null, null, null); - } else { - if (msg instanceof RAttributable && ((RAttributable) msg).getAttributes() != null) { - unserializeAttributes(((RAttributable) msg).getAttributes()); - } - return msg; + @TruffleBoundary + private static RAttributable unserializeAttributable(SerializedAttributable a) throws IOException { + RAttributes attributes = a.getAttributes(); + RAttributable attributable = (RAttributable) RSerialize.unserialize(a.getSerializedAttributable(), null, null, null); + if (attributes != null) { + assert attributable.getAttributes() == null; + // attributes unserialized in caller methods + attributable.initAttributes(attributes); } - } catch (IOException x) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error unserializing msg from the channel"); + return attributable; } - } - public static Object receive(int id) { - RChannel channel = getChannelFromId(id); - try { - Object msg = (id < 0 ? channel.masterToClient : channel.clientToMaster).take(); - return processedReceivedMessage(msg); - } catch (InterruptedException x) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error receiving from the channel"); + @TruffleBoundary + private void unserializeListSlow(RList list) throws IOException { + unserializeList(list); } - } - public static Object poll(int id) { - RChannel channel = getChannelFromId(id); - Object msg = (id < 0 ? channel.masterToClient : channel.clientToMaster).poll(); - if (msg != null) { - return processedReceivedMessage(msg); + @TruffleBoundary + private void unserializeAttributes(RAttributable attributable) throws IOException { + RAttributes attr = attributable.getAttributes(); + for (RAttribute a : attr) { + Object val = a.getValue(); + Object newVal = unserializeObject(val); + if (newVal != val) { + // class attribute is a string vector which should be always shared + assert !a.getName().equals(RRuntime.CLASS_ATTR_KEY); + // TODO: this is a bit brittle as it relies on the iterator to work + // correctly in + // the + // face of updates (which it does under current implementation of + // attributes) + attributable.setAttr(a.getName(), newVal); + } + } } - return null; + + public Object processedReceivedMessage(Object msg) { + try { + return unserializeObject(msg); + } catch (IOException x) { + throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error unserializing msg from the channel"); + } + } + } } 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 4df846f7beb1b36cfa4407146931e273abd2fd59..5069b1fd910103e0225d7f9f780375cce6cf36a3 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 @@ -11,13 +11,22 @@ */ package com.oracle.truffle.r.runtime; +import java.util.ArrayList; + import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE; import com.oracle.truffle.r.runtime.context.ConsoleHandler; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; +import com.oracle.truffle.r.runtime.instrument.InstrumentationState; public class RCleanUp { + private static ArrayList<InstrumentationState.CleanupHandler> cleanupHandlers = new ArrayList<>(); + + public static void registerCleanupHandler(InstrumentationState.CleanupHandler cleanupHandler) { + cleanupHandlers.add(cleanupHandler); + } + public static void cleanUp(SA_TYPE saveType, int status, boolean runLast) { if (RInterfaceCallbacks.R_CleanUp.isOverridden()) { RFFIFactory.getRFFI().getREmbedRFFI().cleanUp(saveType.ordinal(), status, runLast ? 1 : 0); @@ -87,6 +96,14 @@ public class RCleanUp { case SUICIDE: default: + } + for (InstrumentationState.CleanupHandler cleanupHandler : cleanupHandlers) { + try { + cleanupHandler.cleanup(status); + } catch (Throwable t) { + RInternalError.reportError(t); + } + } // TODO run exit finalizers (FFI) // TODO clean tmpdir diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCmdOptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCmdOptions.java index e65017eed639b37248305c574090978ab300f228..657de9e74701338bfaad2c4e7fccf1be75fddc62 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCmdOptions.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCmdOptions.java @@ -368,7 +368,7 @@ public final class RCmdOptions { public static void printHelpAndExit(Client client) { printHelp(client); - System.exit(0); + throw new ExitException(0); } private static void printVersionAndExit() { 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 d3b6c90962ba3b6b1cf9f4f20bc53aa7626f5d9d..785970bd521f4d6985aa39935494d65c5a51df3a 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 @@ -22,10 +22,12 @@ */ package com.oracle.truffle.r.runtime; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.ProcessBuilder.Redirect; +import java.util.zip.GZIPInputStream; import com.oracle.truffle.r.runtime.conn.GZIPConnections.GZIPRConnection; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; @@ -56,11 +58,16 @@ public class RCompression { return null; } + private static final byte GZIP_MAGIC1 = GZIPInputStream.GZIP_MAGIC & 0xFF; + private static final byte GZIP_MAGIC2 = (byte) ((GZIPInputStream.GZIP_MAGIC >> 8) & 0xFF); + /** * Decode the compression type from the bytes in buf (which must be at least length 5). */ - public static Type decodeBuf(byte[] buf) { - if (buf[0] == 'B' && buf[1] == 'Z' && buf[2] == 'h') { + private static Type decodeBuf(byte[] buf) { + if (buf[0] == GZIP_MAGIC1 && buf[1] == GZIP_MAGIC2) { + return RCompression.Type.GZIP; + } else if (buf[0] == 'B' && buf[1] == 'Z' && buf[2] == 'h') { return RCompression.Type.BZIP2; } else if (buf[0] == (byte) 0xFD && buf[1] == '7' && buf[2] == 'z' && buf[3] == 'X' && buf[4] == 'Z') { return RCompression.Type.LZMA; @@ -70,6 +77,17 @@ public class RCompression { } } + public static Type getCompressionType(String path) throws IOException { + try (InputStream is = new FileInputStream(path)) { + byte[] buf = new byte[5]; + int count = is.read(buf); + if (count == 5) { + return RCompression.Type.decodeBuf(buf); + } + } + return RCompression.Type.NONE; + } + public static boolean uncompress(Type type, byte[] udata, byte[] cdata) { switch (type) { case NONE: @@ -105,16 +123,12 @@ public class RCompression { } private static boolean gzipCompress(byte[] udata, byte[] cdata) { - long[] cdatalen = new long[1]; - cdatalen[0] = cdata.length; - int rc = RFFIFactory.getRFFI().getZipRFFI().compress(cdata, cdatalen, udata); + int rc = RFFIFactory.getRFFI().getZipRFFI().compress(cdata, udata); return rc == 0; } private static boolean gzipUncompress(byte[] udata, byte[] data) { - long[] destlen = new long[1]; - destlen[0] = udata.length; - int rc = RFFIFactory.getRFFI().getZipRFFI().uncompress(udata, destlen, data); + int rc = RFFIFactory.getRFFI().getZipRFFI().uncompress(udata, data); return rc == 0; } 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 50a18c02504f470cbfb08d67dc5d3fba23b240de..95e71bd0f2def42beddb04db94bce3f9d6de5e07 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 @@ -21,10 +21,12 @@ import java.util.Map; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RAttributes; import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; import com.oracle.truffle.r.runtime.data.RComplex; @@ -72,6 +74,9 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor; * handled in {@code RASTDeparse} via the {@link RRuntimeASTAccess} interface. */ public class RDeparse { + + private static final RAttributeProfiles DUMMY_ATTR_PROFILES = RAttributeProfiles.create(); + public static final int KEEPINTEGER = 1; public static final int QUOTEEXPRESSIONS = 2; public static final int SHOWATTRIBUTES = 4; @@ -343,7 +348,7 @@ public class RDeparse { public void fixupSources() { Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.DEPARSE); for (SourceSectionElement s : sources) { - s.element.setSourceSection(source.createSection(null, s.start, s.length)); + s.element.setSourceSection(source.createSection(s.start, s.length)); } } @@ -589,7 +594,7 @@ public class RDeparse { } if (value instanceof RExpression) { - append("expression(").appendListContents(((RExpression) value).getList()).append(')'); + append("expression(").appendListContents((RExpression) value).append(')'); } else if (value instanceof RAbstractListVector) { RAbstractListVector obj = (RAbstractListVector) value; try (C c = withAttributes(obj)) { @@ -636,6 +641,8 @@ public class RDeparse { append("<pointer: 0x").append(Long.toHexString(((RExternalPtr) value).getAddr())).append('>'); } else if (value instanceof REnvironment) { append("<environment>"); + } else if (value instanceof TruffleObject) { + append("<truffle object>"); } else { throw RInternalError.shouldNotReachHere("unexpected: " + value); } @@ -956,10 +963,10 @@ public class RDeparse { /** * Handles {@link RList}, (@link RExpression}. Method name same as GnuR. */ - private DeparseVisitor appendListContents(RAbstractListVector v) { + private DeparseVisitor appendListContents(RAbstractVector v) { int n = v.getLength(); boolean lbreak = false; - Object names = v.getNames(); + Object names = v.getNames(DUMMY_ATTR_PROFILES); RStringVector snames = names == RNull.instance ? null : (RStringVector) names; for (int i = 0; i < n; i++) { if (i > 0) { @@ -1061,7 +1068,7 @@ public class RDeparse { root = list.getDataAtAsObject(0); } } - return new DeparseVisitor(false, 80, true, 0, -1, constants).process(root).getContents(); + return new DeparseVisitor(false, 80, true, SHOWATTRIBUTES, -1, constants).process(root).getContents(); } @TruffleBoundary 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 e8d68692064e190abdaae38f28d52c457d599a63..57a8f578e492156cc506b29e464a0565b92f15b0 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 @@ -45,16 +45,22 @@ public final class REnvVars implements RContext.ContextState { private final Map<String, String> envVars = new HashMap<>(System.getenv()); - private REnvVars(RContext context) { + private REnvVars() { + } + + @Override + public RContext.ContextState initialize(RContext context) { + // explicit environment settings in nested contexts must be installed first + checkExplciitEnvSettings(context); // set the standard vars defined by R - String rHome = System.getenv("R_HOME"); + String rHome = envVars.get("R_HOME"); // Always read the system file FileSystem fileSystem = FileSystems.getDefault(); safeReadEnvironFile(fileSystem.getPath(rHome, "etc", "Renviron").toString()); envVars.put("R_DOC_DIR", fileSystem.getPath(rHome, "doc").toString()); envVars.put("R_INCLUDE_DIR", fileSystem.getPath(rHome, "include").toString()); envVars.put("R_SHARE_DIR", fileSystem.getPath(rHome, "share").toString()); - String rLibsUserProperty = System.getenv("R_LIBS_USER"); + String rLibsUserProperty = envVars.get("R_LIBS_USER"); if (rLibsUserProperty == null) { String os = System.getProperty("os.name"); if (os.contains("Mac OS")) { @@ -101,10 +107,26 @@ public final class REnvVars implements RContext.ContextState { System.setProperty("http.proxyPort", port); } } + return this; + } + + public static REnvVars newContextState() { + return new REnvVars(); } - public static REnvVars newContext(RContext context) { - return new REnvVars(context); + private void checkExplciitEnvSettings(RContext context) { + String[] envs = context.getEnvSettings(); + if (envs == null || envs.length == 0) { + return; + } + for (String envdef : envs) { + String[] parts = envdef.split("="); + if (parts.length == 2) { + envVars.put(parts[0], parts[1]); + } else { + // for now just ignore + } + } } private String getEitherCase(String var) { 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 d8ffa9fb2fee02f8fc3948e260d9bf0390e783fc..b40ea24d42fed02822279ed54fc5ea7a56390faf 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 @@ -11,10 +11,11 @@ */ package com.oracle.truffle.r.runtime; +import java.io.IOException; + 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.InteropException; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.runtime.env.REnvironment.PutException; @@ -132,10 +133,15 @@ public final class RError extends RuntimeException { } @TruffleBoundary - public static RError interopError(RBaseNode node, InteropException e, TruffleObject o) { + public static RError interopError(RBaseNode node, Throwable e, TruffleObject o) { throw error0(node, RError.Message.GENERIC, "Foreign function failed: " + (e.getMessage() != null ? e.getMessage() : e.toString()) + " on object " + o); } + @TruffleBoundary + public static RError ioError(RBaseNode node, IOException ex) { + throw error0(node, Message.GENERIC, ex.getMessage()); + } + public static RBaseNode findParentRBase(Node node) { Node current = node; while (current != null) { @@ -230,6 +236,7 @@ public final class RError extends RuntimeException { */ GENERIC("%s"), TOO_SHORT("'%s' is too short"), + VECTOR_SIZE_TOO_LARGE("vector size specified is too large"), ARG_RECYCYLED("an argument will be fractionally recycled"), LENGTH_GT_1("the condition has length > 1 and only the first element will be used"), LENGTH_ZERO("argument is of length zero"), @@ -250,6 +257,7 @@ public final class RError extends RuntimeException { INVALID_ARG_TYPE_UNARY("invalid argument to unary operator"), VECTOR_SIZE_NEGATIVE("vector size cannot be negative"), VECTOR_SIZE_NA("vector size cannot be NA"), + VECTOR_SIZE_NA_NAN("vector size cannot be NA/NaN"), NO_LOOP_FOR_BREAK_NEXT("no loop for break/next, jumping to top level"), INVALID_FOR_SEQUENCE("invalid for() loop sequence"), NO_NONMISSING_MAX("no non-missing arguments to max; returning -Inf"), @@ -262,20 +270,22 @@ public final class RError extends RuntimeException { MUST_BE_SQUARE_COMPATIBLE("'%s' (%d x %d) must be compatible with '%' (%d x %d)"), INVALID_TFB("invalid (to - from)/by in seq(.)"), WRONG_SIGN_IN_BY("wrong sign in 'by' argument"), - WRONG_TYPE("wrong type of argument"), BY_TOO_SMALL("'by' argument is much too small"), INCORRECT_SUBSCRIPTS("incorrect number of subscripts"), INCORRECT_SUBSCRIPTS_MATRIX("incorrect number of subscripts on matrix"), NEGATIVE_EXTENTS_TO_MATRIX("negative extents to matrix"), INVALID_SEP("invalid 'sep' specification"), INVALID_LENGTH("invalid '%s' length"), + INVALID_NA_PRINT_SPEC("invalid 'na.print' specification"), EMPTY_WHAT("empty 'what' specified"), LINE_ELEMENTS("line %d did not have %d elements"), ITEMS_NOT_MULTIPLE("number of items read is not a multiple of the number of columns"), TRACEMEM_NOT_NULL("cannot trace NULL"), // below: GNU R gives also expression for the argument NOT_FUNCTION("'%s' is not a function, character or symbol"), + NOT_A_FUNCTION("'%s' is not a function"), NON_CHARACTER("non-character argument"), + NON_CHARACTER_NAMES("non-character names"), NON_NUMERIC_MATH("non-numeric argument to mathematical function"), NAN_PRODUCED("NaNs produced"), NUMERIC_COMPLEX_MATRIX_VECTOR("requires numeric/complex matrix/vector arguments"), @@ -291,15 +301,16 @@ public final class RError extends RuntimeException { NA_INTRODUCED_COERCION_INT("NAs introduced by coercion to integer range"), ARGUMENT_WHICH_NOT_LOGICAL("argument to 'which' is not logical"), X_NUMERIC("'x' must be numeric"), - X_LIST_ATOMIC("'x' must be list or atomic vector"), + X_LIST_ATOMIC("'x' must be a list or atomic vector"), X_ARRAY_TWO("'x' must be an array of at least two dimensions"), ACCURACY_MODULUS("probable complete loss of accuracy in modulus"), INVALID_SEPARATOR("invalid separator"), INCORRECT_DIMENSIONS("incorrect number of dimensions"), LOGICAL_SUBSCRIPT_LONG("(subscript) logical subscript too long"), - DECREASING_TRUE_FALSE("'decreasing' must be TRUE or FALSE"), ARGUMENT_LENGTHS_DIFFER("argument lengths differ"), ZERO_LENGTH_PATTERN("zero-length pattern"), + UNSUPPORTED_MODE("unsupported mode"), + MODE_LENGTH_ONE("'mode' must be of length at least one"), ALL_CONNECTIONS_IN_USE("all connections are in use"), CANNOT_READ_CONNECTION("cannot read from this connection"), CONNECTION_NOT_OPEN_READ("connection not open for reading"), @@ -311,6 +322,7 @@ public final class RError extends RuntimeException { ONLY_WRITE_BINARY_CONNECTION("can only write to a binary connection"), NOT_A_TEXT_CONNECTION("'con' is not a 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"), TOO_FEW_LINES_READ_LINES("too few lines read in readLineWRITE_ONs"), INVALID_CONNECTION("invalid connection"), @@ -320,11 +332,14 @@ public final class RError extends RuntimeException { COMPARISON_COMPLEX("invalid comparison with complex values"), NON_NUMERIC_BINARY("non-numeric argument to binary operator"), RAW_SORT("raw vectors cannot be sorted"), + ONLY_ATOMIC_CAN_BE_SORTED("only atomic vectors can be sorted"), INVALID_UNNAMED_ARGUMENT("invalid argument"), INVALID_UNNAMED_VALUE("invalid value"), NAMES_NONVECTOR("names() applied to a non-vector"), NAMES_LONGER("'names' attribute [%d] must be the same length as the vector [%d]"), ONLY_FIRST_VARIABLE_NAME("only the first element is used as variable name"), + INVALID_FIRST_FILENAME("invalid first filename"), + INVALID_SECOND_FILENAME("invalid second filename"), INVALID_FIRST_ARGUMENT("invalid first argument"), NO_ENCLOSING_ENVIRONMENT("no enclosing environment"), ASSIGN_EMPTY("cannot assign values in the empty environment"), @@ -332,10 +347,18 @@ public final class RError extends RuntimeException { AS_ENV_NULL_DEFUNCT("using 'as.environment(NULL)' is defunct"), REPLACEMENT_NOT_ENVIRONMENT("replacement object is not an environment"), ARGUMENT_NOT_MATRIX("argument is not a matrix"), + ARGUMENT_NOT_ENVIRONMENT("argument is not an environment"), + ARGUMENT_NAME_NOT_ENVIRONMENT("'%s' is not an environment"), DOLLAR_ATOMIC_VECTORS("$ operator is invalid for atomic vectors"), COERCING_LHS_TO_LIST("Coercing LHS to a list"), + INVALID_LHS("invalid (%s) left side of assignment"), ARGUMENT_NOT_LIST("argument not a list"), FIRST_ARGUMENT_NOT_NAMED_LIST("first argument must be a named list"), + FIRST_ARGUMENT_NOT_CHARVEC("first argument must be a character vector"), + FIRST_ARGUMENT_NOT_FILENAME("first argument must be a filename"), + ARG_MUST_BE_FUNCTION("argument must be a function"), + ASCII_NOT_LOGICAL("'ascii' must be logical"), + MUST_BE_LOGICAL("argument '%s' must be logical"), LIST_NAMES_SAME_LENGTH("names(x) must be a character vector of the same length as x"), DIMS_CONTAIN_NEGATIVE_VALUES("the dims contain negative values"), NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED("negative length vectors are not allowed"), @@ -344,6 +367,7 @@ public final class RError extends RuntimeException { DIMS_CONTAIN_NA("the dims contain missing values"), LENGTH_ZERO_DIM_INVALID("length-0 dimension vector is invalid"), ATTRIBUTES_LIST_OR_NULL("attributes must be a list or NULL"), + SET_ATTRIBUTES_ON_NULL("attempt to set an attribute on NULL"), RECALL_CALLED_OUTSIDE_CLOSURE("'Recall' called from outside a closure"), MATCH_CALL_CALLED_OUTSIDE_FUNCTION("match.call() was called from outside a function"), NOT_NUMERIC_VECTOR("argument is not a numeric vector"), @@ -368,7 +392,7 @@ public final class RError extends RuntimeException { // below: not exactly GNU-R message PROMISE_CYCLE("promise already under evaluation: recursive default argument reference or earlier problems?"), MISSING_ARGUMENTS("'missing' can only be used for arguments"), - INVALID_ENVIRONMENT("invalid environment specified"), + INVALID_ENVIRONMENT("invalid environment"), ENVIR_NOT_LENGTH_ONE("numeric 'envir' arg not of length one"), FMT_NOT_CHARACTER("'fmt' is not a character vector"), UNSUPPORTED_TYPE("unsupported type"), @@ -406,14 +430,17 @@ public final class RError extends RuntimeException { UNKNOWN_FUNCTION_USE_METHOD("no applicable method for '%s' applied to an object of class '%s'"), UNKNOWN_OBJECT("object '%s' not found"), INVALID_ARGUMENT("invalid '%s' argument"), - INVALID_POS_ARGUMENT("invalid 'pos' argument"), + INVALID_ARGUMENT_OF_TYPE("invalid '%s' argument of type '%s'"), INVALID_VALUE("invalid '%s' value"), INVALID_ARGUMENTS_NO_QUOTE("invalid %s arguments"), + INVALID_SUBSCRIPT("invalid subscript"), INVALID_SUBSCRIPT_TYPE("invalid subscript type '%s'"), ARGUMENT_NOT_VECTOR("argument %d is not a vector"), CANNOT_COERCE("cannot coerce type '%s' to vector of type '%s'"), ARGUMENT_ONLY_FIRST("argument '%s' has length > 1 and only the first element will be used"), ARGUMENT_ONLY_FIRST_1("only the first element of '%s' argument used"), + ARGUMENT_WRONG_LENGTH("wrong length for argument"), + ARGUMENT_WRONG_TYPE("wrong type for argument"), CANNOT_OPEN_FILE("cannot open file '%s': %s"), NOT_CONNECTION("'%s' is not a connection"), UNUSED_TEXTCONN("closing unused text connection %d (%s)"), @@ -423,6 +450,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_INTEGER("'%s' must be an integer"), UNUSED_ARGUMENT("unused argument (%s)"), UNUSED_ARGUMENTS("unused arguments (%s)"), INFINITE_MISSING_VALUES("infinite or missing values in '%s'"), @@ -448,6 +476,7 @@ public final class RError extends RuntimeException { ROWS_NOT_MULTIPLE("number of rows of result is not a multiple of vector length (arg %d)"), ARG_ONE_OF("'%s' should be one of %s"), MUST_BE_SQUARE_MATRIX("'%s' must be a square matrix"), + MUST_BE_SQUARE_MATRIX_SPEC("'%s' (%d x %d) must be square"), NON_MATRIX("non-matrix argument to '%s'"), NON_NUMERIC_ARGUMENT_TO("non-numeric argument to '%s'"), DIMS_GT_ZERO("'%s' must have dims > 0"), @@ -460,6 +489,7 @@ public final class RError extends RuntimeException { EXACT_SINGULARITY("exact singularity in '%s'"), SINGULAR_SOLVE("singular matrix '%s' in solve"), SEED_TYPE(".Random.seed is not an integer vector but of type '%s'"), + INVALID_NORMAL_TYPE_IN_RGNKIND("invalid Normal type in 'RNGkind'"), INVALID_USE("invalid use of '%s'"), FORMAL_MATCHED_MULTIPLE("formal argument \"%s\" matched by multiple actual arguments"), ARGUMENT_MATCHES_MULTIPLE("argument %d matches multiple formal arguments"), @@ -479,7 +509,6 @@ public final class RError extends RuntimeException { EXPR_NOT_LENGTH_ONE("EXPR must be a length 1 vector"), EXPR_MISSING("'EXPR' is missing"), INVALID_STORAGE_MODE_UPDATE("invalid to change the storage mode of a factor"), - NULL_VALUE("'value' must be non-null character string"), 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"), @@ -488,11 +517,14 @@ public final class RError extends RuntimeException { ERROR_IN_SAMPLE("Error in sample.int(x, size, replace, prob) : "), INCORRECT_NUM_PROB("incorrect number of probabilities"), NA_IN_PROB_VECTOR("NA in probability vector"), - NEGATIVE_PROBABILITY("non-positive probability"), + NEGATIVE_PROBABILITY("negative probability"), NON_POSITIVE_FILL("non-positive 'fill' argument will be ignored"), MUST_BE_ONE_BYTE("invalid %s: must be one byte"), INVALID_DECIMAL_SEP("invalid decimal separator"), INVALID_QUOTE_SYMBOL("invalid quote symbol set"), + INVALID_TIES_FOR_RANK("invalid ties.method for rank() [should never happen]"), + UNIMPLEMENTED_TYPE_IN_GREATER("unimplemented type '%s' in greater"), + RANK_LARGE_N("parameter 'n' is greater than length(x), GnuR output is non-deterministic, FastR will use n=length(x)"), // below: not exactly GNU-R message TOO_FEW_POSITIVE_PROBABILITY("too few positive probabilities"), DOTS_BOUNDS("The ... list does not contain %s elements"), @@ -526,6 +558,7 @@ public final class RError extends RuntimeException { ARGUMENTS_PASSED_0_1("0 arguments passed to '%s' which requires 1"), ARGUMENT_IGNORED("argument '%s' will be ignored"), NOT_CHARACTER_VECTOR("'%s' must be a character vector"), + WRONG_WINSLASH("'winslash' must be '/' or '\\\\\\\\'"), CANNOT_MAKE_VECTOR_OF_MODE("vector: cannot make a vector of mode '%s'"), SET_ROWNAMES_NO_DIMS("attempt to set 'rownames' on an object with no dimensions"), COLUMNS_NOT_MULTIPLE("number of columns of result is not a multiple of vector length (arg %d)"), @@ -559,7 +592,6 @@ public final class RError extends RuntimeException { PARSE_ERROR("parse error"), SEED_NOT_VALID_INT("supplied seed is not a valid integer"), POSITIVE_CONTEXTS("number of contexts must be positive"), - INVALID_TIMES_ARG("invalid 'times' value"), NORMALIZE_PATH_NOSUCH("path[%d]=\"%s\": No such file or directory"), ARGS_MUST_BE_NAMED("all arguments must be named"), INVALID_INTERNAL("invalid .Internal() argument"), @@ -608,6 +640,7 @@ public final class RError extends RuntimeException { FILE_OPEN_TMP("file(\"\") only supports open = \"w+\" and open = \"w+b\": using the former"), FILE_APPEND_WRITE("write error during file append"), REQUIRES_CHAR_VECTOR("'%s' requires a character vector"), + ARGUMENT_NOT_CHAR_VECTOR("argument is not a character vector"), NOT_VALID_NAMES("not a valid named list"), CHAR_ARGUMENT("character argument expected"), CANNOT_BE_INVALID("'%s' cannot be NA, NaN or infinite"), @@ -642,7 +675,7 @@ public final class RError extends RuntimeException { REG_FINALIZER_FIRST("first argument must be environment or external pointer"), REG_FINALIZER_SECOND("second argument must be a function"), REG_FINALIZER_THIRD("third argument must be 'TRUE' or 'FALSE'"), - LAZY_LOAD_DB_CORRUPT("lazy-load database '%s' is corrupt"), + LAZY_LOAD_DB_CORRUPT("lazy-load database '%s' is corrupt or unreadable"), MAGIC_EMPTY("restore file may be empty -- no data loaded"), MAGIC_TOONEW("restore file may be from a newer version of R -- no data loaded"), MAGIC_CORRUPT("bad restore file magic number (file may be corrupted) -- no data loaded"), @@ -669,6 +702,7 @@ public final class RError extends RuntimeException { INVALID_PRIM_METHOD_CODE("invalid primitive methods code (\"%s\"): should be \"clear\", \"reset\", \"set\", or \"suppress\""), PRIM_GENERIC_NOT_FUNCTION("the formal definition of a primitive generic must be a function object (got type '%s')"), NON_INTEGER_VALUE("non-integer value %s qualified with L; using numeric value"), + NON_INTEGER_N("non-integer %s = %f"), INTEGER_VALUE_DECIAML("integer literal %s contains decimal; using numeric value"), INTEGER_VALUE_UNNECESARY_DECIMAL("integer literal %s contains unnecessary decimal point"), NON_LANG_ASSIGNMENT_TARGET("target of assignment expands to non-language object"), @@ -686,7 +720,30 @@ public final class RError extends RuntimeException { ROWSUM_NAMES_NOT_CHAR("row names are not character"), ROWSUM_NON_NUMERIC("non-numeric matrix in rowsum(): this should not happen"), ARGUMENTS_REQUIRED_COUNT("%d arguments to '%s' which requires %d"), - ARGUMENT_LENGTH_0("argument of length 0"); + ARG_IS_NOT_OF_MODE("argument is not of mode %s"), + ARGUMENT_LENGTH_0("argument of length 0"), + MUST_BE_VECTOR_BUT_WAS("'%s' must be of a vector type, was '%s'"), + SYSTEM_CHAR_ARG("non-empty character argument expected"), + SYSTEM_INTERN_NOT_NA("'intern' must be logical and not NA"), + NO_SUCH_FILE("cannot open file '%s': No such file or directory"), + NON_STRING_ARG_TO_INTERNAL_PASTE("non-string argument to Internal paste"), + INVALID_STRING_IN_STOP(" [invalid string in stop(.)]"), + INVALID_STRING_IN_WARNING(" [invalid string in warning(.)]"), + ERR_MSG_MUST_BE_STRING("error message must be a character string"), + ERR_MSG_BAD("bad error message"), + BAD_ENVIRONMENT("bad %s environment argument"), + CANNOT_BE_LENGTH("'%s' cannot be of length %d"), + SECOND_ARGUMENT_LIST("second argument must be a list"), + DOES_NOT_HAVE_DIMNAMES("'%s' does not have named dimnames"), + ATTEMPT_TO_REPLICATE("attempt to replicate an object of type '%s'"), + ATTEMPT_TO_REPLICATE_NO_VECTOR("attempt to replicate non-vector"), + INCORRECT_ARG_TYPE("incorrect type for %s argument"), + INVALID_ARG_OF_LENGTH("invalid %s argument of length %d"), + INVALID_FILENAME_PATTERN("invalid filename pattern"), + INVALID_FILE_EXT("invalid file extension"), + NO("no '%s'"), + APPLIES_TO_VECTORS("%s applies only to vectors"), + GAP_MUST_BE_NON_NEGATIVE("'gap' must be non-negative integer"); 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 74aff0e6602d52b7bdc9cc54b91f01276aa6dd41..af99cbf6c7b6d7d62046e0d61ddd373c17a9866a 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 @@ -145,7 +145,7 @@ public class RErrorHandling { return dotSignalSimpleWarning; } - public static ContextStateImpl newContext(@SuppressWarnings("unused") RContext context) { + public static ContextStateImpl newContextState() { return new ContextStateImpl(); } } @@ -573,17 +573,13 @@ public class RErrorHandling { private static void warningCallInvoke(Object call, RStringVector warningMessage) { /* * Warnings generally do not prevent results being printed. However, this call into R will - * destroy any visibility setting made by the calling builtin prior to this call. So we save - * and restore it across the call. + * destroy any visibility setting made by the calling builtin prior to this call. + * + * TODO: it's not clear whether this is still the case with the optimized visibility scheme */ ContextStateImpl errorHandlingState = getRErrorHandlingState(); - boolean visibility = RContext.getInstance().isVisible(); - try { - RFunction f = errorHandlingState.getDotSignalSimpleWarning(); - RContext.getRRuntimeASTAccess().callback(f, new Object[]{warningMessage, call}); - } finally { - RContext.getInstance().setVisible(visibility); - } + RFunction f = errorHandlingState.getDotSignalSimpleWarning(); + RContext.getRRuntimeASTAccess().callback(f, new Object[]{warningMessage, call}); } private static void warningcallDfltWithCall(Object call, Message msg, Object... args) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java index 6c37aa8fc0438910b700a425e486c660de50f7cd..dc57b2b69c7cb57f9e09908765a1bbb1328e7d20 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java @@ -27,6 +27,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.r.runtime.context.Engine.ParseException; import com.oracle.truffle.r.runtime.context.RContext; @@ -52,6 +53,7 @@ public final class RInternalCode { this.basePackage = basePackage; } + @TruffleBoundary public static Source loadSourceRelativeTo(Class<?> clazz, String fileName) { return Utils.getResourceAsSource(clazz, fileName); } @@ -64,7 +66,7 @@ public final class RInternalCode { evaluatedEnvironment.setParent(statsPackage); // caller is put into arguments by eval, internal code is assumed to be well-behaved and // not accessing it - context.getThisEngine().eval(parsedCode, evaluatedEnvironment, /* caller: */null); + context.getThisEngine().eval(parsedCode, evaluatedEnvironment, RCaller.createInvalid(null)); return evaluatedEnvironment; } catch (ParseException e) { throw e.throwAsRError(); @@ -102,7 +104,7 @@ public final class RInternalCode { codes.put(source, code); } - public static ContextStateImpl newContext(@SuppressWarnings("unused") RContext context) { + public static ContextStateImpl newContextState() { return new ContextStateImpl(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java index 012d2a4f2af7b6b943c90c753acf7df1eea8d362..05c614c25acbde2a40fb38145f061baccf255cd9 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java @@ -18,6 +18,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.context.RContext.ContextKind; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -50,12 +51,15 @@ public class ROptions { * The current values for a given context. */ private final HashMap<String, Object> map; + private final REnvVars envVars; - private ContextStateImpl(HashMap<String, Object> map) { + private ContextStateImpl(HashMap<String, Object> map, REnvVars envVars) { this.map = map; + this.envVars = envVars; // cannot call updateDotOptions here } + @TruffleBoundary public Set<Entry<String, Object>> getValues() { Set<Map.Entry<String, Object>> result = new HashSet<>(); for (Map.Entry<String, Object> entry : map.entrySet()) { @@ -66,6 +70,7 @@ public class ROptions { return result; } + @TruffleBoundary public Object getValue(String name) { Object value = map.get(name); if (value == null) { @@ -74,6 +79,7 @@ public class ROptions { return value; } + @TruffleBoundary public Object setValue(String name, Object value) throws OptionsException { Object coercedValue = value; if (CHECKED_OPTIONS_SET.contains(name)) { @@ -90,14 +96,20 @@ public class ROptions { return previous; } - public static ContextStateImpl newContext(RContext context, REnvVars envVars) { + @TruffleBoundary + public static ContextStateImpl newContextState(REnvVars envVars) { HashMap<String, Object> map = new HashMap<>(); + return new ContextStateImpl(map, envVars); + } + + @Override + public RContext.ContextState initialize(RContext context) { if (context.getKind() == ContextKind.SHARE_NOTHING) { applyDefaults(map, context.getStartParams(), envVars); } else { map.putAll(context.getParent().stateROptions.map); } - return new ContextStateImpl(map); + return this; } /** diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RPerfStats.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RPerfStats.java deleted file mode 100644 index e655114e7aeec6d48bcc99bda719ed83909fb540..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RPerfStats.java +++ /dev/null @@ -1,211 +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.runtime; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.util.ArrayList; - -/** - * Manage the creation/activation of handlers or performance analysis. Enabled by the - * {@code FastROptions.Option.PerfStats} option. - * - * The handlers are all registered statically from the class wanting to participate. The handlers - * are enabled selectively at runtime based on the command line option. An enabled handler gets a - * call to its {@link Handler#initialize(String)} method so that it can enable its perf-mode - * behavior. - */ -public class RPerfStats { - - public interface Handler { - /** - * Called on startup if enabled to initialize any necessary state. - * - * @param optionText any text after the handler name on the command line - */ - void initialize(String optionText); - - String getName(); - - void report(); - } - - public static class Histogram { - private final long[] hist; - private int maxSize = -1; - - public Histogram(int buckets) { - hist = new long[buckets + 1]; - } - - public void inc(int size) { - if (size > maxSize) { - maxSize = size; - } - hist[effectiveBucket(size)]++; - } - - public void dec(int size) { - hist[effectiveBucket(size)]--; - } - - public int numBuckets() { - return hist.length - 1; - } - - public long getMaxSize() { - return maxSize; - } - - public int effectiveBucket(int size) { - if (size > hist.length - 1) { - return hist.length - 1; - } else { - return size; - } - } - - public long getTotalCount() { - long totalCount = 0; - for (int i = 0; i < hist.length; i++) { - totalCount += hist[i]; - } - return totalCount; - } - - public void report() { - long maxCount = -1; - for (int i = 0; i < hist.length; i++) { - if (hist[i] > maxCount) { - maxCount = hist[i]; - } - } - int fieldWidth = Long.toString(maxCount).length() + 1; - if (fieldWidth < 10) { - fieldWidth = 10; - } - String fieldWidthString = Integer.toString(fieldWidth); - String sFormat = "%-" + fieldWidthString + "s"; - String dFormat = "%-" + fieldWidthString + "d"; - out().printf(sFormat, "Size"); - for (int i = 0; i < hist.length - 1; i++) { - out().printf(dFormat, i); - } - out().printf(sFormat, "> " + (hist.length - 1)); - out().println(); - out().printf(sFormat, "Count"); - for (int i = 0; i < hist.length - 1; i++) { - out().printf(dFormat, hist[i]); - } - out().printf(dFormat, hist[hist.length - 1]); - out().println(); - } - } - - private static final ArrayList<Handler> handlers = new ArrayList<>(); - private static boolean initialized; - private static PrintStream out = System.out; - - public static PrintStream out() { - return out; - } - - /** - * Register a {@link Handler}. This should be done in a {@code static} block so that, in an AOT - * VM, all handlers are included in the image. N.B. Owing to dynamic class loading in a standard - * VM, this may be called after {@link RPerfStats#initialize}, so we may have to invoke - * {@code handler.initialize} from here. - */ - public static void register(Handler handler) { - handlers.add(handler); - if (initialized) { - String optionText = getOptionText(handler.getName()); - if (optionText != null) { - handler.initialize(optionText); - } - } - } - - /** - * Called by the engine startup sequence to initialize all registered handlers. - */ - public static void initialize() { - for (Handler handler : handlers) { - String optionText = getOptionText(handler.getName()); - if (optionText != null) { - handler.initialize(optionText); - } - } - initialized = true; - } - - private static String getOptionText(String name) { - String optionValue = getPerfStatsOption(name); - if (optionValue != null) { - if (optionValue.length() > 0) { - optionValue = optionValue.substring(name.length()); - } - } - return optionValue; - } - - private static String getPerfStatsOption(String name) { - return FastROptions.matchesElement(name, FastROptions.PerfStats.getStringValue()); - } - - public static boolean enabled(String name) { - return getPerfStatsOption(name) != null; - } - - private static boolean reporting; - - /** - * Called just before FastR exits. - */ - public static void report() { - if (reporting) { - // some crash in a reporter caused a recursive entry - return; - } - reporting = true; - String file = FastROptions.PerfStatsFile.getStringValue(); - if (file != null) { - try { - out = new PrintStream(new FileOutputStream(file)); - } catch (IOException ex) { - System.err.print("PerfStats: can't open " + file + " for output, using stdout"); - } - } - boolean headerOutput = false; - for (Handler handler : handlers) { - if (enabled(handler.getName())) { - if (!headerOutput) { - out().println("RPerfStats Reports"); - headerOutput = true; - } - handler.report(); - } - } - } -} 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 2522a7fbeeea4765c298c3010b875d219369c949..3af2daa50e1ea8b7403d0e223a2bc9e9ddf3bfbf 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 @@ -38,7 +38,14 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory; */ public final class RProfile implements RContext.ContextState { - private RProfile(RContext context, REnvVars envVars) { + private final REnvVars envVars; + + private RProfile(REnvVars envVars) { + this.envVars = envVars; + } + + @Override + public RContext.ContextState initialize(RContext context) { String rHome = REnvVars.rHome(); FileSystem fileSystem = FileSystems.getDefault(); Source newSiteProfile = null; @@ -77,10 +84,11 @@ public final class RProfile implements RContext.ContextState { } siteProfile = newSiteProfile; userProfile = newUserProfile; + return this; } - private final Source siteProfile; - private final Source userProfile; + private Source siteProfile; + private Source userProfile; public static Source systemProfile() { Path path = FileSystems.getDefault().getPath(REnvVars.rHome(), "library", "base", "R", "Rprofile"); @@ -108,7 +116,7 @@ public final class RProfile implements RContext.ContextState { } } - public static RProfile newContext(RContext context, REnvVars envVars) { - return new RProfile(context, envVars); + public static RProfile newContextState(REnvVars envVars) { + return new RProfile(envVars); } } 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 e568055e0e7c3c70cfe5dc137d89702871104dbf..3ebe4d8f547d127781d537a5912b168f64349e53 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,9 +11,6 @@ */ package com.oracle.truffle.r.runtime; -import java.text.DecimalFormat; -import java.util.Locale; - import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; @@ -329,6 +326,12 @@ public class RRuntime { return int2complex(raw2int(r)); } + public static String rawToHexString(RRaw operand) { + int value = raw2int(operand); + char[] digits = new char[]{Character.forDigit((value & 0xF0) >> 4, 16), Character.forDigit(value & 0x0F, 16)}; + return new String(digits); + } + @TruffleBoundary public static String rawToString(RRaw operand) { return intToString(raw2int(operand)); @@ -339,14 +342,20 @@ public class RRuntime { @TruffleBoundary public static int string2intNoCheck(String s, boolean exceptionOnFail) { // FIXME use R rules + int result; try { - return Integer.decode(s); // decode supports hex constants + result = Integer.decode(s); // decode supports hex constants } catch (NumberFormatException e) { if (exceptionOnFail) { throw e; } + return INT_NA; } - return INT_NA; + + if (result == INT_NA && exceptionOnFail) { + throw new NumberFormatException(); + } + return result; } @TruffleBoundary @@ -544,61 +553,6 @@ public class RRuntime { return isNAorNaN(d) ? createComplexNA() : double2complexNoCheck(d); } - @TruffleBoundary - public static String doubleToString(double operand, int digitsBehindDot) { - return isNA(operand) ? STRING_NA : doubleToStringNoCheck(operand, digitsBehindDot); - } - - @TruffleBoundary - public static String doubleToStringNoCheck(double operand, int digitsBehindDot) { - if (doubleIsInt(operand)) { - return intToStringNoCheck((int) operand); - } - if (operand == Double.POSITIVE_INFINITY) { - return "Inf"; - } - if (operand == Double.NEGATIVE_INFINITY) { - return "-Inf"; - } - if (Double.isNaN(operand)) { - return STRING_NaN; - } - - /* - * DecimalFormat format = new DecimalFormat(); format.setMaximumIntegerDigits(12); - * format.setMaximumFractionDigits(12); format.setGroupingUsed(false); return - * format.format(operand); - */ - if (operand < 1000000000000L && ((long) operand) == operand) { - return Long.toString((long) operand); - } - if (operand > 1000000000000L) { - return String.format((Locale) null, "%.6e", operand); - } - // if (true || operand < 0.0001) { - // // not quite correct but better than nothing for now... - // return String.format((Locale) null, "%.22e", new BigDecimal(operand)); - // } - if (digitsBehindDot == -1) { - return Double.toString(operand); - } else { - StringBuilder sb = new StringBuilder("#."); - for (int i = 0; i < digitsBehindDot; i++) { - sb.append('#'); - } - DecimalFormat df = new DecimalFormat(sb.toString()); - return df.format(operand); - } - } - - public static String doubleToStringNoCheck(double operand) { - return doubleToStringNoCheck(operand, -1); - } - - public static String doubleToString(double operand) { - return isNA(operand) ? STRING_NA : doubleToStringNoCheck(operand); - } - public static int double2rawIntValue(double operand) { return isNA(operand) ? 0 : ((int) operand) & 0xFF; } @@ -633,16 +587,6 @@ public class RRuntime { return isNA(c) ? LOGICAL_NA : complex2doubleNoCheck(c); } - @TruffleBoundary - public static String complexToStringNoCheck(RComplex operand) { - return doubleToString(operand.getRealPart()) + "+" + doubleToString(operand.getImaginaryPart()) + "i"; - } - - @TruffleBoundary - public static String complexToString(RComplex operand) { - return isNA(operand) ? STRING_NA : complexToStringNoCheck(operand); - } - public static int complex2rawIntValue(RComplex c) { return isNA(c) ? 0 : ((int) c.getRealPart() & 0xFF); } @@ -670,7 +614,7 @@ public class RRuntime { if (object instanceof Integer) { return intToString((int) object); } else if (object instanceof Double) { - return doubleToString((double) object); + return Double.toString((double) object); } else if (object instanceof Byte) { return logicalToString((byte) object); } 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 2e76ac5fd5339dc612c4b842641b8277b85af9b2..8b082d88f35f86ed2c9f88c0631680d4b96c5cdc 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 @@ -26,6 +26,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.RComplex; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RList; @@ -83,17 +84,6 @@ public interface RRuntimeASTAccess { RSyntaxFunction getSyntaxFunction(RFunction f); - /** - * Serialize a runtime value that requires non-standard treatment. - */ - Object serialize(RSerialize.State state, Object f); - - /** - * Helper function for {@code serialize} working around cyclic dependency. {@code node} is an - * {@RNode}. - */ - void serializeNode(RSerialize.State state, Object node); - /** * Returns the real caller associated with {@code rl}, by locating the {@code RSyntaxNode} * associated with the node stored with {@code rl}. @@ -181,14 +171,31 @@ public interface RRuntimeASTAccess { */ boolean isTaggedWith(Node node, Class<?> tag); - RBaseNode createReadVariableNode(String name); - - RBaseNode createConstantNode(Object o); - boolean enableDebug(RFunction func, boolean once); boolean disableDebug(RFunction func); boolean isDebugged(RFunction func); + /* + * Support for R/RScript sessions ("processes") in an isolated RContext, see + * .fastr.context.r/rscript. The args are everything you might legally enter into a + * shell,including I/O redirection. The result is an integer status code if "intern==false", + * otherwise it is a character vector of the output, with a 'status' attribute containing the + * status code. The env arguments are an optional settings of environment variables of the form + * X=Y. + */ + + Object rcommandMain(String[] args, String[] env, boolean intern); + + Object rscriptMain(String[] args, String[] env, boolean intern); + + String encodeDouble(double x); + + String encodeDouble(double x, int digits); + + String encodeComplex(RComplex x); + + String encodeComplex(RComplex x, int digits); + } 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 0458c3a7369cfffb28cffde127ee8ee907db8eeb..d0817ba5237595ce31d44d938e5f70d1e61ec27c 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 @@ -19,6 +19,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; +import java.lang.ref.WeakReference; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Deque; @@ -26,6 +27,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; +import java.util.WeakHashMap; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; @@ -68,10 +70,18 @@ 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.RAbstractRawVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; import com.oracle.truffle.r.runtime.instrument.RPackageSource; import com.oracle.truffle.r.runtime.nodes.RBaseNode; +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; // Code loosely transcribed from GnuR serialize.c. @@ -200,7 +210,7 @@ public class RSerialize { return dotDotFindNamespace; } - public static ContextStateImpl newContext(@SuppressWarnings("unused") RContext context) { + public static ContextStateImpl newContextState() { return new ContextStateImpl(); } } @@ -215,21 +225,9 @@ public class RSerialize { return i >> 8; } - private abstract static class Common { - + public abstract static class RefCounter { protected Object[] refTable = new Object[128]; protected int refTableIndex; - protected final CallHook hook; - protected final ContextStateImpl contextState; - - protected Common(CallHook hook) { - this.hook = hook; - this.contextState = getContextState(); - } - - protected static IOException formatError(byte format, boolean ok) throws IOException { - throw new IOException("serialized stream format " + (ok ? "not implemented" : "not recognized") + ": " + format); - } protected Object addReadRef(Object item) { assert item != null; @@ -255,6 +253,22 @@ public class RSerialize { } } + private abstract static class Common extends RefCounter { + + protected final CallHook hook; + protected final ContextStateImpl contextState; + + protected Common(CallHook hook) { + this.hook = hook; + this.contextState = getContextState(); + } + + protected static IOException formatError(byte format, boolean ok) throws IOException { + throw new IOException("serialized stream format " + (ok ? "not implemented" : "not recognized") + ": " + format); + } + + } + public static final int DEFAULT_VERSION = 2; /** @@ -310,6 +324,26 @@ public class RSerialize { return result; } + @TruffleBoundary + public static RPromise unserializePromise(RExpression expr, Object e, Object value) { + assert expr.getLength() == 1; + RBaseNode rep; + if (expr.getDataAt(0) instanceof RLanguage) { + RLanguage lang = (RLanguage) expr.getDataAt(0); + rep = lang.getRep(); + } else if (expr.getDataAt(0) instanceof RSymbol) { + rep = RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, ((RSymbol) expr.getDataAt(0)).getName(), false).asRNode(); + } else { + rep = RContext.getASTBuilder().constant(RSyntaxNode.SOURCE_UNAVAILABLE, expr.getDataAt(0)).asRNode(); + } + if (value == RUnboundValue.instance) { + REnvironment env = e == RNull.instance ? REnvironment.baseEnv() : (REnvironment) e; + return RDataFactory.createPromise(PromiseState.Explicit, Closure.create(rep), env.getFrame()); + } else { + return RDataFactory.createEvaluatedPromise(Closure.create(rep), value); + } + } + private static class Input extends Common { protected final PInputStream stream; @@ -610,21 +644,7 @@ public class RSerialize { String deparse = RDeparse.deparseDeserialize(constants, pl.cdr()); RExpression expr = parse(constants, deparse); assert expr.getLength() == 1; - RBaseNode rep; - if (expr.getDataAt(0) instanceof RLanguage) { - RLanguage lang = (RLanguage) expr.getDataAt(0); - rep = lang.getRep(); - } else if (expr.getDataAt(0) instanceof RSymbol) { - rep = RContext.getRRuntimeASTAccess().createReadVariableNode(((RSymbol) expr.getDataAt(0)).getName()); - } else { - rep = RContext.getRRuntimeASTAccess().createConstantNode(expr.getDataAt(0)); - } - if (pl.car() == RUnboundValue.instance) { - REnvironment env = pl.getTag() == RNull.instance ? REnvironment.baseEnv() : (REnvironment) pl.getTag(); - result = RDataFactory.createPromise(PromiseState.Explicit, Closure.create(rep), env.getFrame()); - } else { - result = RDataFactory.createEvaluatedPromise(Closure.create(rep), pl.car()); - } + result = unserializePromise(expr, pl.getTag(), pl.car()); break; } @@ -674,7 +694,7 @@ public class RSerialize { data[i] = elem; } if (type == SEXPTYPE.EXPRSXP) { - result = RDataFactory.createExpression(RDataFactory.createList(data)); + result = RDataFactory.createExpression(data); } else { // this could (ultimately) be a list, factor or dataframe result = RDataFactory.createList(data); @@ -940,9 +960,9 @@ public class RSerialize { if (attrValue instanceof RShareable && ((RShareable) attrValue).isTemporary()) { ((RShareable) attrValue).incRefCount(); } - if (result instanceof RVector && tag.equals(RRuntime.CLASS_ATTR_KEY)) { + if (result instanceof RVector<?> && tag.equals(RRuntime.CLASS_ATTR_KEY)) { RStringVector classes = (RStringVector) attrValue; - result = ((RVector) result).setClassAttr(classes); + result = ((RVector<?>) result).setClassAttr(classes); } else { rAttributable.setAttr(tag, attrValue); } @@ -1115,6 +1135,8 @@ public class RSerialize { private int size; private int offset; + private final WeakHashMap<String, WeakReference<String>> strings = RContext.getInstance().stringMap; + XdrInputFormat(InputStream is) { super(is); if (is instanceof PByteArrayInputStream) { @@ -1167,6 +1189,14 @@ public class RSerialize { result = new String(buf, offset, len, StandardCharsets.UTF_8); } offset += len; + WeakReference<String> entry; + if ((entry = strings.get(result)) != null) { + String string = entry.get(); + if (string != null) { + return string; + } + } + strings.put(result, new WeakReference<>(result)); return result; } @@ -1281,20 +1311,35 @@ public class RSerialize { @Override void writeString(String value) throws IOException { - byte[] bytes = value.getBytes(); - int bytesLen = bytes.length; - int totalLen = bytesLen + 4; - if (totalLen > buf.length) { - // too large to fit buffer - ensureSpace(4); - writeInt(bytesLen); - flushBuffer(); - os.write(bytes); + boolean simple = true; + for (int i = 0; i < value.length(); i++) { + if (value.charAt(i) >= 0x80) { + simple = false; + break; + } + } + if (simple && value.length() <= buf.length) { + writeInt(value.length()); + ensureSpace(value.length()); + for (int i = 0; i < value.length(); i++) { + buf[offset++] = (byte) value.charAt(i); + } } else { - ensureSpace(totalLen); - writeInt(bytesLen); - System.arraycopy(bytes, 0, buf, offset, bytesLen); - offset += bytesLen; + byte[] bytes = value.getBytes(); + int bytesLen = bytes.length; + int totalLen = bytesLen + 4; + if (totalLen > buf.length) { + // too large to fit buffer + ensureSpace(4); + writeInt(bytesLen); + flushBuffer(); + os.write(bytes); + } else { + ensureSpace(totalLen); + writeInt(bytesLen); + System.arraycopy(bytes, 0, buf, offset, bytesLen); + offset += bytesLen; + } } } @@ -1356,10 +1401,6 @@ public class RSerialize { protected final POutputStream stream; private int version; - private Output(RConnection conn, int format, int version, CallHook hook) throws IOException { - this(conn.getOutputStream(), format, version, hook); - } - private Output(OutputStream os, int format, int version, CallHook hook) throws IOException { super(hook); this.version = version; @@ -1571,15 +1612,15 @@ public class RSerialize { case EXPRSXP: case VECSXP: { - RList list; + RAbstractVector list; if (type == SEXPTYPE.EXPRSXP) { - list = ((RExpression) obj).getList(); + list = (RExpression) obj; } else { list = (RList) obj; } stream.writeInt(list.getLength()); for (int i = 0; i < list.getLength(); i++) { - Object listObj = list.getDataAt(i); + Object listObj = list.getDataAtAsObject(i); writeItem(listObj); } break; @@ -1681,7 +1722,7 @@ public class RSerialize { switch (type) { case FUNSXP: { RFunction fun = (RFunction) obj; - RPairList pl = (RPairList) RContext.getRRuntimeASTAccess().serialize(state, fun); + RPairList pl = (RPairList) serializeLanguageObject(state, fun); assert pl != null; state.convertUnboundValues(pl); if (FastROptions.debugMatches("printWclosure")) { @@ -1694,7 +1735,7 @@ public class RSerialize { } case PROMSXP: { - RPairList pl = (RPairList) RContext.getRRuntimeASTAccess().serialize(state, obj); + RPairList pl = (RPairList) serializeLanguageObject(state, obj); assert pl != null; state.convertUnboundValues(pl); if (pl.getTag() != RNull.instance) { @@ -1716,7 +1757,7 @@ public class RSerialize { } case LANGSXP: { - RPairList pl = (RPairList) RContext.getRRuntimeASTAccess().serialize(state, obj); + RPairList pl = (RPairList) serializeLanguageObject(state, obj); state.convertUnboundValues(pl); writeItem(pl.car()); obj = pl.cdr(); @@ -1872,11 +1913,10 @@ public class RSerialize { * {@code serialize} method. On return the caller is responsible for removing the virtual * pairlist with {@link State#closePairList()} and assigning it into the appropriate field ( * {@code car} or {@code cdr}) of it's virtual pairlist. - * */ - public abstract static class State { + private abstract static class State { - protected final Output output; + @SuppressWarnings("unused") protected final Output output; private Map<String, RSymbol> symbolMap = new HashMap<>(); private State(Output output) { @@ -1935,12 +1975,6 @@ public class RSerialize { */ public abstract void setNull(); - /** - * Checks for the special case where the active pairlist has a {@link RNull} {@code car} and - * {@code cdr} and an unset {@code tag}. - */ - public abstract boolean isNull(); - /** * Closes the current pairlist, handling the case where a "simple" value is down-shifted * from a pairlist to just the value. @@ -1959,17 +1993,6 @@ public class RSerialize { */ public abstract void linkPairList(int n); - /** - * Handles the special case of '[', where the indices and "drop/exact" values are in - * different parts of the AST but need to be in the same list. - */ - public abstract void setPositionsLength(int n); - - /** - * Returns value from previous call to {@link #setPositionsLength(int)}. - */ - public abstract int getPositionsLength(); - /** * Special case where the value is in the {@code cdr} and it needs to be in the {@code car}. */ @@ -1990,23 +2013,6 @@ public class RSerialize { setCar(RMissing.instance); } - public void setAsBuiltin(String name) { - setAsLangType(); - setCarAsSymbol(name); - } - - public void serializeNodeSetCar(Object node) { - openPairList(); - RContext.getRRuntimeASTAccess().serializeNode(this, node); - setCar(closePairList()); - } - - public void serializeNodeSetCdr(Object node, SEXPTYPE type) { - openPairList(type); - RContext.getRRuntimeASTAccess().serializeNode(this, node); - setCdr(closePairList()); - } - RSymbol findSymbol(String name) { RSymbol symbol = symbolMap.get(name); if (symbol == null) { @@ -2024,8 +2030,6 @@ public class RSerialize { private static class PLState extends State { private static final RPairList NULL = RDataFactory.createPairList(); private Deque<RPairList> active = new LinkedList<>(); - private int[] positionsLength = new int[10]; - private int px = 0; private PLState(Output output) { super(output); @@ -2118,12 +2122,6 @@ public class RSerialize { } } - @Override - public boolean isNull() { - RPairList pl = active.peekFirst(); - return pl.getTag() == RUnboundValue.instance && pl.car() == RNull.instance && pl.cdr() == RNull.instance; - } - @Override public void switchCdrToCar() { RPairList pl = active.removeFirst(); @@ -2160,17 +2158,6 @@ public class RSerialize { } } - @Override - public void setPositionsLength(int n) { - positionsLength[px++] = n; - } - - @Override - public int getPositionsLength() { - px--; - return positionsLength[px]; - } - @Override public void convertUnboundValues(RPairList pl) { Object obj = pl; @@ -2204,9 +2191,46 @@ public class RSerialize { } } + @TruffleBoundary + public static byte[] serializePromiseRep(RPromise promise) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + Output output = new Output(out, XDR, DEFAULT_VERSION, null); + State state = new PLState(output); + state.openPairList(); + new SerializeVisitor(state).accept(promise.getRep().asRSyntaxNode()); + Object res = state.closePairList(); + if (res instanceof RPairList) { + state.convertUnboundValues((RPairList) res); + } + output.serialize(state, res); + return out.toByteArray(); + } catch (IOException ex) { + throw RInternalError.shouldNotReachHere(); + } + } + + @TruffleBoundary + public static byte[] serializeFunctionNonEnv(RFunction fn) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + Output output = new Output(out, XDR, DEFAULT_VERSION, null); + State state = new PLState(output); + state.openPairList(SEXPTYPE.CLOSXP); + serializeFunctionDefinition(state, (RSyntaxFunction) fn.getRootNode()); + Object res = state.closePairList(); + // CLOSXP-type ensures that the list is not shrunk + state.convertUnboundValues((RPairList) res); + output.serialize(state, res); + return out.toByteArray(); + } catch (IOException ex) { + throw RInternalError.shouldNotReachHere(); + } + } + @TruffleBoundary public static void serialize(RConnection conn, Object obj, int type, int version, Object refhook) throws IOException { - Output output = new Output(conn, type, version, (CallHook) refhook); + Output output = new Output(conn.getOutputStream(), type, version, (CallHook) refhook); State state = new PLState(output); output.serialize(state, obj); } @@ -2277,4 +2301,225 @@ public class RSerialize { out.write('\n'); } } + + private static final class SerializeVisitor extends RSyntaxVisitor<Void> { + + private final State state; + + SerializeVisitor(State state) { + this.state = state; + } + + @Override + protected Void visit(RSyntaxCall element) { + state.setAsLangType(); + state.openPairList(); + accept(element.getSyntaxLHS()); + state.setCar(state.closePairList()); + RSyntaxElement[] arguments = element.getSyntaxArguments(); + RSyntaxElement lhs = element.getSyntaxLHS(); + if (isColon(lhs)) { + // special case, have to translate Identifier names to Symbols + for (int i = 0; i < 2; i++) { + RSyntaxElement arg = arguments[i]; + state.openPairList(); + if (arg instanceof RSyntaxLookup) { + state.setCarAsSymbol(((RSyntaxLookup) arg).getIdentifier()); + } else { + state.setCar(((RSyntaxConstant) arg).getValue()); + } + } + state.linkPairList(2); + state.setCdr(state.closePairList()); + } else { + boolean infixFieldAccess = false; + if (lhs instanceof RSyntaxLookup) { + String name = ((RSyntaxLookup) lhs).getIdentifier(); + infixFieldAccess = "$".equals(name) || "@".equals(name); + } + serializeArguments(arguments, element.getSyntaxSignature(), infixFieldAccess); + } + return null; + } + + private static boolean isColon(RSyntaxElement element) { + if (element instanceof RSyntaxLookup) { + String name = ((RSyntaxLookup) element).getIdentifier(); + return name.equals("::") || name.equals(":::"); + } + return false; + } + + private void serializeArguments(RSyntaxElement[] arguments, ArgumentsSignature signature, boolean infixFieldAccess) { + state.openPairList(SEXPTYPE.LISTSXP); + if (arguments.length == 0) { + state.setNull(); + } else { + for (int i = 0; i < arguments.length; i++) { + RSyntaxElement argument = arguments[i]; + String name = signature.getName(i); + if (name != null) { + state.setTagAsSymbol(name); + } + if (argument == null) { + state.setCarMissing(); + } else { + if (infixFieldAccess && i == 1 && argument instanceof RSyntaxConstant) { + RSyntaxConstant c = (RSyntaxConstant) argument; + String identifier = RRuntime.asStringLengthOne(c.getValue()); + assert identifier != null; + state.setCarAsSymbol(identifier); + } else { + state.openPairList(); + accept(argument); + state.setCar(state.closePairList()); + } + } + if (i != arguments.length - 1) { + state.openPairList(); + } + + } + state.linkPairList(arguments.length); + } + state.setCdr(state.closePairList()); + } + + @Override + protected Void visit(RSyntaxConstant element) { + if (element.getValue() == RMissing.instance) { + state.setCar(RMissing.instance); + } else { + state.setCar(element.getValue()); + } + return null; + } + + @Override + protected Void visit(RSyntaxLookup element) { + state.setCarAsSymbol(element.getIdentifier()); + return null; + } + + @Override + protected Void visit(RSyntaxFunction element) { + state.setAsLangType(); + state.setCarAsSymbol("function"); + state.openPairList(SEXPTYPE.LISTSXP); + state.setCar(visitFunctionFormals(element)); + state.openPairList(SEXPTYPE.LISTSXP); + state.setCdr(visitFunctionBody(element)); + state.switchCdrToCar(); + state.openPairList(SEXPTYPE.LISTSXP); + state.setCar(RNull.instance); + state.setCdr(RNull.instance); + state.setCdr(state.closePairList()); + state.setCdr(state.closePairList()); + state.setCdr(state.closePairList()); + return null; + } + + /** + * Serialize a function's formal arguments. On entry {@code state} has an active pairlist, + * whose {@code tag} is the enclosing {@link REnvironment}. The {@code car} will be set to + * the pairlist representing the formal arguments (or {@link RNull} if none). Each formal + * argument is represented as a pairlist: + * <ul> + * <li>{@code tag}: RSymbol(name)</li> + * <li>{@code car}: Missing or default value</li> + * <li>{@code cdr}: if last formal then RNull else pairlist for next argument. + * </ul> + */ + public Object visitFunctionFormals(RSyntaxFunction element) { + ArgumentsSignature signature = element.getSyntaxSignature(); + RSyntaxElement[] defaults = element.getSyntaxArgumentDefaults(); + if (signature.getLength() > 0) { + for (int i = 0; i < signature.getLength(); i++) { + state.openPairList(); + state.setTagAsSymbol(signature.getName(i)); + if (defaults[i] != null) { + state.openPairList(); + accept(defaults[i]); + state.setCar(state.closePairList()); + } else { + state.setCarMissing(); + } + } + state.linkPairList(signature.getLength()); + return state.closePairList(); + } else { + return RNull.instance; + } + } + + /** + * Serialize a function's body. On entry {@code state} has an active pairlist, whose + * {@code tag} is the enclosing {@link REnvironment}. The {@code cdr} to the pairlist + * representing the body. The body is never empty as the syntax "{}" has a value, however if + * the body is a simple expression, e.g. {@code function(x) x}, the body is not represented + * as a pairlist, just a SYMSXP, which is handled transparently in + * {@code RSerialize.State.closePairList()}. + */ + public Object visitFunctionBody(RSyntaxFunction element) { + state.openPairList(); + accept(element.getSyntaxBody()); + return state.closePairList(); + } + } + + private static Object serializeLanguageObject(RSerialize.State state, Object obj) { + if (obj instanceof RFunction) { + return RSerialize.serializeFunction(state, (RFunction) obj); + } else if (obj instanceof RLanguage) { + return RSerialize.serializeLanguage(state, (RLanguage) obj); + } else if (obj instanceof RPromise) { + return RSerialize.serializePromise(state, (RPromise) obj); + } else { + throw RInternalError.unimplemented("serialize"); + } + } + + private static Object serializeFunction(State state, RFunction f) { + RSyntaxFunction function = (RSyntaxFunction) f.getRootNode(); + REnvironment env = REnvironment.frameToEnvironment(f.getEnclosingFrame()); + state.openPairList().setTag(env); + serializeFunctionDefinition(state, function); + return state.closePairList(); + } + + private static void serializeFunctionDefinition(State state, RSyntaxFunction function) { + SerializeVisitor visitor = new SerializeVisitor(state); + state.setCar(visitor.visitFunctionFormals(function)); + state.setCdr(visitor.visitFunctionBody(function)); + } + + private static Object serializeLanguage(State state, RLanguage lang) { + RSyntaxElement element = lang.getRep().asRSyntaxNode(); + state.openPairList(SEXPTYPE.LANGSXP); + new SerializeVisitor(state).accept(element); + return state.closePairList(); + } + + private static Object serializePromise(State state, RPromise promise) { + /* + * If the promise is evaluated, we store the value (in car) and the tag is set to RNull, + * else we record the environment in the tag and store RUnboundValue. In either case we + * record the expression. + */ + Object value; + Object tag; + if (promise.isEvaluated()) { + value = promise.getValue(); + tag = RNull.instance; + } else { + value = RUnboundValue.instance; + tag = promise.getFrame() == null ? REnvironment.globalEnv() : REnvironment.frameToEnvironment(promise.getFrame()); + } + state.openPairList().setTag(tag); + state.setCar(value); + state.openPairList(); + new SerializeVisitor(state).accept(promise.getRep().asRSyntaxNode()); + state.setCdr(state.closePairList()); + return state.closePairList(); + } } 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 29ebcd0c94c992a08fc2e6a3b616eb2e6b9c140a..75b14bc3ea0c23fdb5a510a1e391312e01113ad8 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 @@ -29,6 +29,7 @@ import java.net.URISyntaxException; import java.net.URL; import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.api.source.SourceSection; /** * A facade for the creation of Truffle {@link Source} objects, which is complicated in R due the @@ -74,7 +75,9 @@ public class RSource { DEPARSE_ERROR("<package_deparse_error>"), LAPPLY("<lapply>"), R_PARSEVECTOR("<R_ParseVector>"), - PAIRLIST_DEPARSE("<pairlist deparse>"); + PAIRLIST_DEPARSE("<pairlist deparse>"), + INIT_EMBEDDED("<init embedded>"), + R_IMPL("<internal R code>"); public final String string; @@ -88,14 +91,10 @@ 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) { + public static Source fromFileName(String text, String path) throws URISyntaxException { File file = new File(path).getAbsoluteFile(); - try { - URI uri = new URI("file://" + file.getAbsolutePath()); - return Source.newBuilder(text).name(file.getName()).uri(uri).mimeType(RRuntime.R_APP_MIME).build(); - } catch (URISyntaxException ex) { - throw RInternalError.shouldNotReachHere(ex); - } + URI uri = new URI("file://" + file.getAbsolutePath()); + return Source.newBuilder(text).name(file.getName()).uri(uri).mimeType(RRuntime.R_APP_MIME).build(); } /** @@ -157,6 +156,13 @@ public class RSource { return Source.newBuilder(url).name(name).mimeType(RRuntime.R_APP_MIME).build(); } + /** + * Create an unknown source with the given name. + */ + public static SourceSection createUnknown(String name) { + return Source.newBuilder("").name(name).mimeType(RRuntime.R_APP_MIME).build().createSection(0, 0); + } + /** * If {@code source} was created with {@link #fromPackageTextInternal} return the * "package:name", else {@code null}. This can be used to access the corresponding R 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 fc6702711628c8866bc4337c40b1205e77a626df..9da38a9af9e03e131dadae2b0f7bc36b94c89fea 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 @@ -182,7 +182,7 @@ public enum RType { } } - public RVector getEmpty() { + public RVector<?> getEmpty() { switch (this) { case Double: return RDataFactory.createEmptyDoubleVector(); @@ -203,7 +203,7 @@ public enum RType { } } - public RVector create(int length, boolean fillNA) { + public RVector<?> create(int length, boolean fillNA) { switch (this) { case Logical: return RDataFactory.createLogicalVector(length, fillNA); @@ -215,10 +215,16 @@ public enum RType { return RDataFactory.createComplexVector(length, fillNA); case Character: return RDataFactory.createStringVector(length, fillNA); - case List: + case Expression: { + Object[] data = new Object[length]; + Arrays.fill(data, RNull.instance); + return RDataFactory.createExpression(data); + } + case List: { Object[] data = new Object[length]; Arrays.fill(data, RNull.instance); return RDataFactory.createList(data); + } case Raw: return RDataFactory.createRawVector(length); default: diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVisibility.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVisibility.java index 13ca96cb3447c2232ac49f272b3c5af48633c254..71b1b6b13307a62ba374554419b47fe444dcb07c 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVisibility.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVisibility.java @@ -23,8 +23,6 @@ package com.oracle.truffle.r.runtime; -import com.oracle.truffle.r.runtime.context.RContext; - /** * Denotes the visibility of an output of a built-in. */ @@ -33,9 +31,9 @@ public enum RVisibility { OFF, /** * In GnuR this means by default ON, but C code can change the visibility. In FastR this means - * that is it left up to the built-in whether and how to call - * {@link RContext#setVisible(boolean)}. For example, {@code do.call} and similar built-ins do - * not change the visibility set by the 'inner' node. + * that is it left up to the built-in whether and how to use {@code SetVisibilityNode}. For + * example, {@code do.call} and similar built-ins do not change the visibility set by the + * 'inner' node. */ CUSTOM, } 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 a7f2336b164e2b6ddc45890727e81496b39e8277..0fddff7ddb5511d204ab70cce66397c540d59db1 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 @@ -34,7 +34,7 @@ public abstract class ResourceHandlerFactory { public interface Handler { /** * See {@link java.lang.Class#getResource(String)}. - * + * * @return The path component of the {@link java.net URL} returned by * {@link java.lang.Class#getResource(String)} */ @@ -58,7 +58,7 @@ public abstract class ResourceHandlerFactory { private static ResourceHandlerFactory theInstance; - private static ResourceHandlerFactory getInstance() { + public static ResourceHandlerFactory getInstance() { return theInstance; } 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 8733ab397016e835599532c18d617f86ab877e7b..3e693cfc72fe03074163ea8e5beb33411a420228 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 @@ -26,7 +26,6 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.net.URL; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Path; @@ -91,13 +90,20 @@ public final class Utils { graphPrinter.printToNetwork(true); } + /** + * Locates a resource that is used within the implementation, e.g. a file of R code, and returns + * a {@link Source} instance that represents it. Since the location may vary between + * implementations and, in particular may not be a persistently accessible URL, we read the + * content and store it as an "internal" instance. + */ public static Source getResourceAsSource(Class<?> clazz, String resourceName) { try { - URL url = ResourceHandlerFactory.getHandler().getResource(clazz, resourceName); - if (url == null) { - throw RInternalError.shouldNotReachHere("resource " + resourceName + " not found, context: " + clazz); + InputStream is = ResourceHandlerFactory.getHandler().getResourceAsStream(clazz, resourceName); + if (is == null) { + throw new IOException(); } - return RSource.fromURL(url, resourceName); + String content = getResourceAsString(is); + return RSource.fromTextInternal(content, RSource.Internal.R_IMPL); } catch (IOException ex) { throw RInternalError.shouldNotReachHere("resource " + resourceName + " not found, context: " + clazz); } @@ -169,6 +175,15 @@ public final class Utils { throw new ExitException(2); } + /** + * This the real, final, non-overrideable, exit of the entire R system. TODO well, modulo how + * quit() is interpreted when R is started implicitly from a Polyglot shell that is running + * other languages. + */ + public static void systemExit(int status) { + System.exit(status); + } + private static String userHome; private static String userHome() { @@ -295,6 +310,14 @@ public final class Utils { return tildeExpand(path, false); } + public static String unShQuote(String s) { + if (s.charAt(0) == '\'') { + return s.substring(1, s.length() - 1); + } else { + return s; + } + } + /** * Retrieve a frame from the call stack. N.B. To avoid the iterator overhead use * {@link #getActualCurrentFrame()} for the current frame. @@ -868,4 +891,20 @@ public final class Utils { } return r; } + + @TruffleBoundary + public static String intern(String s) { + return s.intern(); + } + + @TruffleBoundary + public static String toString(Object obj) { + return obj.toString(); + } + + @TruffleBoundary + public static String stringFormat(String format, Object... objects) { + return String.format(format, objects); + } + } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/FastPathFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/FastPathFactory.java index 59271ee152afc1d898158e4c11f9195f983d8785..494ef0ba2c953fbfcb6e0b3d757ee2e8f75429b8 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/FastPathFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/FastPathFactory.java @@ -38,10 +38,30 @@ import com.oracle.truffle.r.runtime.nodes.RFastPathNode; * the function is invoked, the fast path is invoked first and only if it returns {@code null}, then * the original implementation is invoked. */ -@FunctionalInterface public interface FastPathFactory { - FastPathFactory EVALUATE_ARGS = () -> null; + FastPathFactory EVALUATE_ARGS = new FastPathFactory() { + + @Override + public RFastPathNode create() { + return null; + } + + @Override + public RVisibility getVisibility() { + return null; + } + + @Override + public boolean evaluatesArgument(int index) { + return true; + } + + @Override + public boolean forcedEagerPromise(int index) { + return false; + } + }; FastPathFactory FORCED_EAGER_ARGS = new FastPathFactory() { @@ -50,6 +70,11 @@ public interface FastPathFactory { return null; } + @Override + public RVisibility getVisibility() { + return null; + } + @Override public boolean evaluatesArgument(int index) { return false; @@ -83,23 +108,46 @@ public interface FastPathFactory { } return true; } + + @Override + public boolean forcedEagerPromise(int index) { + return false; + } }; } - RFastPathNode create(); + static FastPathFactory fromVisibility(RVisibility visibility, Supplier<RFastPathNode> factory) { + return new FastPathFactory() { + @Override + public RFastPathNode create() { + return factory.get(); + } - default boolean evaluatesArgument(@SuppressWarnings("unused") int index) { - return true; - } + @Override + public RVisibility getVisibility() { + return visibility; + } + + @Override + public boolean evaluatesArgument(int index) { + return true; + } - default boolean forcedEagerPromise(@SuppressWarnings("unused") int index) { - return false; + @Override + public boolean forcedEagerPromise(int index) { + return false; + } + }; } + RFastPathNode create(); + + boolean evaluatesArgument(int index); + + boolean forcedEagerPromise(int index); + /** * Visibility of the output. This corresponds to {@link RBuiltin#visibility()} */ - default RVisibility getVisibility() { - return RVisibility.ON; - } + RVisibility getVisibility(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltin.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltin.java index e609182b11595ff2f1aac89f4ddf3f1449b2d5e6..d904fd823e9194910f97c7afd5a0a235cfac9e41 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltin.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltin.java @@ -63,7 +63,7 @@ public @interface RBuiltin { /** * The visibility of the output of the builtin. If the visibility is set to * {@link RVisibility#CUSTOM}, then it is responsibility of the execute method/specializations - * to set the visibility in {@link com.oracle.truffle.r.runtime.context.RContext}. + * to set the visibility in using {@code SetVisibilityNode}. */ RVisibility visibility() default RVisibility.ON; 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 9581723641af720712061a2b12ab6e1a364de750..11aa28cc2fa2c4d83594ceebfdbd0195056f6d0d 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 @@ -45,12 +45,14 @@ public abstract class RBuiltinDescriptor { private final boolean alwaysSplit; private final RDispatch dispatch; private final RBehavior behavior; + private final RSpecialFactory specialCall; private final int primitiveMethodIndex; @CompilationFinal private final boolean[] evaluatesArgument; public RBuiltinDescriptor(String name, Class<?> builtinNodeClass, RVisibility visibility, String[] aliases, RBuiltinKind kind, ArgumentsSignature signature, int[] nonEvalArgs, boolean splitCaller, - boolean alwaysSplit, RDispatch dispatch, RBehavior behavior) { + boolean alwaysSplit, RDispatch dispatch, RBehavior behavior, RSpecialFactory specialCall) { + this.specialCall = specialCall; this.name = name.intern(); this.builtinNodeClass = builtinNodeClass; this.visibility = visibility; @@ -131,4 +133,8 @@ public abstract class RBuiltinDescriptor { public RBehavior getBehavior() { return behavior; } + + public RSpecialFactory getSpecialCall() { + return specialCall; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RSpecialFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RSpecialFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..6319f73d631d3b0e61ed414806bba74da696e6f6 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RSpecialFactory.java @@ -0,0 +1,50 @@ +/* + * 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.runtime.builtins; + +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.nodes.RNode; + +/** + * A builtin can have a node that can handle very simple cases for which (unlike with fast-path) no + * argument matching has to be performed. Such simple case node, called special, is created for the + * built-in by AST builder by default. If the special node cannot handle its arguments, it throws + * {@link #FULL_CALL_NEEDED} and the it will be replaced with call to the full blown built-in. + */ +public interface RSpecialFactory { + RuntimeException FULL_CALL_NEEDED = new FullCallNeededException(); + + /** + * Returns a 'special node' if the given arguments with their signature can be handled by it. If + * if returns {@code null}, the full blown built-in node will be created. + */ + RNode create(ArgumentsSignature argumentsSignature, RNode[] arguments); + + @SuppressWarnings("serial") + final class FullCallNeededException extends RuntimeException { + @Override + public synchronized Throwable fillInStackTrace() { + return null; + } + } +} 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 58a135e705e73f61cd5b64a1d618a6887615c5dd..3a77d377e1efc512c34ba49461afb6616cd1d789 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 @@ -179,7 +179,7 @@ public class ConnectionSupport { } } - public static ContextStateImpl newContext(@SuppressWarnings("unused") RContext context) { + public static ContextStateImpl newContextState() { return new ContextStateImpl(); } } @@ -333,7 +333,7 @@ public class ConnectionSupport { * if the result isn't actually a valid connection, e.g. * {@code structure(2, class=c("terminal","connection"))}. */ - public static RConnection fromVector(RVector vector, @SuppressWarnings("unused") RStringVector classAttr) { + public static RConnection fromVector(RVector<?> vector, @SuppressWarnings("unused") RStringVector classAttr) { int index = RRuntime.asInteger(vector); RConnection result = RContext.getInstance().stateRConnection.getConnection(index); if (result == null) { 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 050f147d9f1ecb0eb7bd7afd8d6cc057746b6506..c4eb346b86a2cca0350bbe63a901c244642c0ed6 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 @@ -34,6 +34,7 @@ import java.nio.ByteBuffer; import java.util.zip.GZIPInputStream; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.runtime.RCompression; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.TempPathName; @@ -102,24 +103,17 @@ public class FileConnections { FileReadTextRConnection(BasePathRConnection base) throws IOException { super(base); - inputStream = new BufferedInputStream(new FileInputStream(base.path)); // can be compressed - check for it - inputStream.mark(2); - int byte1 = inputStream.read(); - if (byte1 == -1) { - inputStream.reset(); - } else { - int byte2 = inputStream.read(); - if (byte2 == -1) { - inputStream.reset(); - } else { - if (byte1 == (GZIPInputStream.GZIP_MAGIC & 0x000000FF) && byte2 == (GZIPInputStream.GZIP_MAGIC >> 8)) { - inputStream.close(); - inputStream = new GZIPInputStream(new FileInputStream(base.path), GZIPConnections.GZIP_BUFFER_SIZE); - } else { - inputStream.reset(); - } - } + 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), GZIPConnections.GZIP_BUFFER_SIZE); + break; + default: + throw RError.nyi(RError.SHOW_CALLER2, "compression type: " + cType.name()); } } @@ -212,10 +206,10 @@ public class FileConnections { } } - private static class FileReadBinaryRConnection extends DelegateReadRConnection implements ReadWriteHelper { + static class FileReadBinaryRConnection extends DelegateReadRConnection implements ReadWriteHelper { private FileInputStream inputStream; - FileReadBinaryRConnection(FileRConnection base) throws IOException { + FileReadBinaryRConnection(BasePathRConnection base) throws IOException { super(base); inputStream = new FileInputStream(base.path); } @@ -316,7 +310,7 @@ public class FileConnections { private static class FileReadWriteConnection extends DelegateReadWriteRConnection implements ReadWriteHelper { /* * This is a minimal implementation to support one specific use in package installation. - * + * * N.B. R mandates separate "position" offsets for reading and writing (pain). This code is * pessimistic and assumes interleaved reads and writes, so does a lot of probably redundant * seeking. It could be optimized. diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/GZIPConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/GZIPConnections.java index 66fcbb33a01d59c5967f7114ada79141440d2efa..0928fe7df3d31e81432526ff5988f60fb0eebb83 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/GZIPConnections.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/GZIPConnections.java @@ -60,20 +60,18 @@ public class GZIPConnections { @Override protected void createDelegateConnection() throws IOException { DelegateRConnection delegate = null; - switch (getOpenMode().abstractOpenMode) { + AbstractOpenMode openMode = getOpenMode().abstractOpenMode; + switch (openMode) { case Read: case ReadBinary: - RCompression.Type cType = RCompression.Type.NONE; - try (InputStream is = new FileInputStream(path)) { - byte[] buf = new byte[5]; - int count = is.read(buf); - if (count == 5) { - cType = RCompression.Type.decodeBuf(buf); - } - } + RCompression.Type cType = RCompression.getCompressionType(path); switch (cType) { case NONE: - delegate = new FileConnections.FileReadTextRConnection(this); + if (openMode == AbstractOpenMode.ReadBinary) { + delegate = new FileConnections.FileReadBinaryRConnection(this); + } else { + delegate = new FileConnections.FileReadTextRConnection(this); + } break; case GZIP: delegate = new GZIPInputRConnection(this); 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 b54b5995afd58769b1094ffc7740fc74f9be1ee4..4939a1c008c1c6cd9d4840df95e5b3f1441205df 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 @@ -331,7 +331,7 @@ public abstract class RConnection extends RAttributeStorage implements AutoClose public abstract boolean isOpen(); /* - * Methods from the RAbstractContainer interface, which is implemented to allow an RVector to + * Methods from the RAbstractContainer interface, which is implemented to allow an RVector<?>to * transform to an RConnection via a class update. */ 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 a8436ff49f669512583d889c7190c43352383dd5..22f8ca5d238f1834edc99797045c60ffdbac47c8 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 @@ -51,25 +51,27 @@ public class StdConnections { } public static final class ContextStateImpl implements RContext.ContextState { - private final StdinConnection stdin; - private final StdoutConnection stdout; - private final StderrConnection stderr; + private StdinConnection stdin; + private StdoutConnection stdout; + private StderrConnection stderr; private final Diversion[] diversions = new Diversion[20]; private int top = -1; - private ContextStateImpl(StdinConnection stdin, StdoutConnection stdout, StderrConnection stderr) { - this.stdin = stdin; - this.stdout = stdout; - this.stderr = stderr; + public static ContextStateImpl newContextState() { + return new ContextStateImpl(); } - public static ContextStateImpl newContext(RContext context) { + @Override + public RContext.ContextState initialize(RContext context) { ConsoleHandler consoleHandler = context.getConsoleHandler(); try { - return new ContextStateImpl(new StdinConnection(), new StdoutConnection(consoleHandler), new StderrConnection(consoleHandler)); + stdin = new StdinConnection(); + stdout = new StdoutConnection(consoleHandler); + stderr = new StderrConnection(consoleHandler); } catch (IOException ex) { throw Utils.rSuicide("failed to open stdconnections:"); } + return this; } } 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 131397b5d5b24fca57d33a6ebe44410d424d863b..781156ff27b2b2ae3d7d66fc72940b0d0c19f42a 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 @@ -22,14 +22,12 @@ */ package com.oracle.truffle.r.runtime.context; -import java.io.IOException; import java.util.TimeZone; 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.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RStartParams; import com.oracle.truffle.r.runtime.context.RContext.ContextKind; @@ -45,6 +43,7 @@ public final class ContextInfo implements TruffleObject { private static final AtomicInteger contextInfoIds = new AtomicInteger(); private final RStartParams startParams; + private final String[] env; private final RContext.ContextKind kind; private final TimeZone systemTimeZone; @@ -57,8 +56,9 @@ public final class ContextInfo implements TruffleObject { private final int id; private PolyglotEngine vm; - private ContextInfo(RStartParams startParams, 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) { this.startParams = startParams; + this.env = env; this.kind = kind; this.parent = parent; this.consoleHandler = consoleHandler; @@ -72,37 +72,44 @@ public final class ContextInfo implements TruffleObject { return newVM; } + public PolyglotEngine createVM(PolyglotEngine.Builder builder) { + PolyglotEngine newVM = builder.globalSymbol(GLOBAL_SYMBOL, this).build(); + this.vm = newVM; + return newVM; + } + /** * Create a context configuration object. * - * @param parent if non-null {@code null}, the parent creating the context + * @param startParams the start parameters passed this R session + * @param env TODO * @param kind defines the degree to which this context shares base and package environments * with its parent - * @param startParams the start parameters passed this R session + * @param parent if non-null {@code null}, the parent creating the context * @param consoleHandler a {@link ConsoleHandler} for output * @param systemTimeZone the system's time zone */ - public static ContextInfo create(RStartParams startParams, ContextKind kind, RContext parent, ConsoleHandler consoleHandler, TimeZone systemTimeZone) { + public static ContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler, TimeZone systemTimeZone) { int id = contextInfoIds.incrementAndGet(); - return new ContextInfo(startParams, kind, parent, consoleHandler, systemTimeZone, id); + return new ContextInfo(startParams, env, kind, parent, consoleHandler, systemTimeZone, id); } - public static ContextInfo create(RStartParams startParams, ContextKind kind, RContext parent, ConsoleHandler consoleHandler) { - return create(startParams, kind, parent, consoleHandler, TimeZone.getDefault()); + public static ContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler) { + return create(startParams, env, kind, parent, consoleHandler, TimeZone.getDefault()); } public static ContextInfo getContextInfo(PolyglotEngine vm) { - try { - return (ContextInfo) vm.findGlobalSymbol(ContextInfo.GLOBAL_SYMBOL).get(); - } catch (IOException ex) { - throw RInternalError.shouldNotReachHere(); - } + return (ContextInfo) vm.findGlobalSymbol(ContextInfo.GLOBAL_SYMBOL).get(); } public RStartParams getStartParams() { return startParams; } + public String[] getEnv() { + return env; + } + public ContextKind getKind() { return kind; } 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 f6c0f60ed573f8ce488923a6dcb895dc1b938963..330f46c849ec03ab2e440a41f1ca7cba95e70e8c 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 @@ -22,10 +22,10 @@ */ package com.oracle.truffle.r.runtime.context; -import java.io.IOException; import java.util.Map; import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.source.Source; @@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode; public interface Engine { - class ParseException extends IOException { + class ParseException extends RuntimeException { private static final long serialVersionUID = 1L; private final Source source; @@ -57,6 +57,7 @@ public interface Engine { this.line = line; } + @TruffleBoundary public RError throwAsRError() { if (source.getLineCount() == 1) { throw RError.error(RError.NO_CALLER, RError.Message.UNEXPECTED, token, substring); @@ -65,6 +66,7 @@ public interface Engine { } } + @TruffleBoundary public void report(ConsoleHandler consoleHandler) { String msg; if (source.getLineCount() == 1) { 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 c21d8b5555efa5960fd7a0b924d696a7a711cad9..7d8a42aa6afaabc25c5715e09213557e37163725 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 @@ -23,10 +23,12 @@ package com.oracle.truffle.r.runtime.context; import java.io.Closeable; -import java.io.IOException; +import java.util.EnumSet; +import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.Map; import java.util.TimeZone; +import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import com.oracle.truffle.api.Assumption; @@ -34,6 +36,7 @@ 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.instrumentation.Instrumenter; import com.oracle.truffle.api.interop.ForeignAccess; @@ -42,7 +45,6 @@ import com.oracle.truffle.api.nodes.InvalidAssumptionException; 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.FastROptions; import com.oracle.truffle.r.runtime.LazyDBCache; import com.oracle.truffle.r.runtime.PrimitiveMethodsInfo; import com.oracle.truffle.r.runtime.RCmdOptions; @@ -51,19 +53,18 @@ import com.oracle.truffle.r.runtime.REnvVars; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RErrorHandling; import com.oracle.truffle.r.runtime.RInternalCode.ContextStateImpl; -import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; -import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; -import com.oracle.truffle.r.runtime.builtins.RBuiltinLookup; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.ROptions; 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.RStartParams; import com.oracle.truffle.r.runtime.RSource; -import com.oracle.truffle.r.runtime.RVisibility; +import com.oracle.truffle.r.runtime.RStartParams; import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; +import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; +import com.oracle.truffle.r.runtime.builtins.RBuiltinLookup; import com.oracle.truffle.r.runtime.conn.ConnectionSupport; import com.oracle.truffle.r.runtime.conn.StdConnections; import com.oracle.truffle.r.runtime.context.Engine.ParseException; @@ -139,12 +140,51 @@ public final class RContext extends ExecutionContext implements TruffleObject { public static final ContextKind[] VALUES = values(); } + /** + * Defines the life cycle of an {@link RContext}. + */ + private enum State { + /** + * The {@link RContext} object has been constructed, but not initialized. + */ + CONSTRUCTED, + /** + * The thread has been attached, so {@link #getInstance} may be called, but initialization + * has not completed. + */ + ATTACHED, + /** + * The {@link RContext} object has been initialized by the {@link #initializeContext} + * method, but is not active in the sense that the associated {@link Engine} instance has + * been activated. + */ + INITIALIZED, + /** + * The associated {@link Engine} instance has been activated. + */ + ACTIVE, + /** + * The {@link RContext} object has been destroyed by the {@link #destroy} method. All + * subsequent operations ideally should throw {@link IllegalStateException}. + */ + DESTROYED + } + /** * Tagging interface denoting a (usually inner-) class that carries the context-specific state * for a class that has context-specific state. The class specific state must implement this * interface. */ public interface ContextState { + /** + * Initialize the state. The initial creation should involve minimal computation; any + * significant computation should be handled in this method. + */ + @SuppressWarnings("unused") + default ContextState initialize(RContext context) { + return this; + } + /** * Called in response to the {@link RContext#destroy} method. Provides a hook for finalizing * any state before the context is destroyed. @@ -159,7 +199,7 @@ public final class RContext extends ExecutionContext implements TruffleObject { * A thread that is explicitly associated with a context for efficient lookup. */ public abstract static class ContextThread extends Thread { - private RContext context; + protected RContext context; public ContextThread(RContext context) { this.context = context; @@ -195,39 +235,44 @@ public final class RContext extends ExecutionContext implements TruffleObject { PolyglotEngine vm = info.createVM(); try { setContext(vm.eval(GET_CONTEXT).as(RContext.class)); - } catch (Exception e1) { - throw new RInternalError(e1, "error while initializing eval thread"); + } catch (Throwable t) { + throw new RInternalError(t, "error while initializing eval thread"); } try { - try { - PolyglotEngine.Value resultValue = vm.eval(source); - evalResult = createEvalResult(resultValue); - } catch (ParseException e) { - e.report(info.getConsoleHandler()); - evalResult = createErrorResult(e.getMessage()); - } catch (IOException e) { - Throwable cause = e.getCause(); - if (cause instanceof ExitException) { - // termination, treat this as "success" - ExitException exitException = (ExitException) cause; - evalResult = RDataFactory.createList(new Object[]{exitException.getStatus()}); - } else { - // some internal error - RInternalError.reportErrorAndConsoleLog(cause, info.getConsoleHandler(), info.getId()); - evalResult = createErrorResult(cause.getClass().getSimpleName()); - } - } + evalResult = run(vm, info, source); } finally { vm.dispose(); threads.remove(info.getId()); } } + /** + * Convenience method for {@code .fastr.context.eval} in same thread. + */ + public static RList run(PolyglotEngine vm, ContextInfo info, Source source) { + RList evalResult; + try { + PolyglotEngine.Value resultValue = vm.eval(source); + evalResult = createEvalResult(resultValue); + } catch (ParseException e) { + e.report(info.getConsoleHandler()); + evalResult = createErrorResult(e.getMessage()); + } catch (ExitException e) { + // termination, treat this as "success" + evalResult = RDataFactory.createList(new Object[]{e.getStatus()}); + } catch (Throwable t) { + // some internal error + RInternalError.reportErrorAndConsoleLog(t, info.getConsoleHandler(), info.getId()); + evalResult = createErrorResult(t.getClass().getSimpleName()); + } + return evalResult; + } + /** * The result is an {@link RList} contain the value, plus an "error" attribute if the * evaluation resulted in an error. */ - public static RList createEvalResult(PolyglotEngine.Value resultValue) throws IOException { + private static RList createEvalResult(PolyglotEngine.Value resultValue) { Object result = resultValue.get(); Object listResult = result; String error = null; @@ -262,12 +307,6 @@ public final class RContext extends ExecutionContext implements TruffleObject { private final ContextInfo info; private final Engine engine; - /** - * Denote whether the result of an expression should be printed in the shell or not. This value - * will be modified by many operations like builtins, block statements, etc. - */ - private boolean resultVisible = false; - /** * A context-specific value that is checked in {@code HiddenInternalFunctions} to avoid an error * report on a {@code SUBSTITUTE} builtin. Not worth promoting to a {@link ContextState}. @@ -284,10 +323,10 @@ public final class RContext extends ExecutionContext implements TruffleObject { * performing the evaluation, so we can store the {@link RContext} in a {@link ThreadLocal}. * * When a context is first created no threads are attached, to allow contexts to be used as - * values in the experimental {@code fastr.createcontext} function. Additional threads can be + * values in the experimental {@code fastr.context.xxx} functions. Additional threads can be * added by the {@link #attachThread} method. */ - public static final ThreadLocal<RContext> threadLocalContext = new ThreadLocal<>(); + private static final ThreadLocal<RContext> threadLocalContext = new ThreadLocal<>(); /** * Used by the MethodListDispatch class. @@ -298,16 +337,10 @@ public final class RContext extends ExecutionContext implements TruffleObject { private boolean nullS4Object = false; - private boolean active; + private EnumSet<State> state = EnumSet.noneOf(State.class); private PrimitiveMethodsInfo primitiveMethodsInfo; - /** - * A (hopefully) temporary workaround to ignore the setting of {@link #resultVisible} for - * benchmarks. Set across all contexts. - */ - @CompilationFinal private static boolean ignoreVisibility; - /** * Set to {@code true} when in embedded mode to allow other parts of the system to determine * whether embedded mode is in effect, <b>before</b> the initial context is created. @@ -330,7 +363,7 @@ public final class RContext extends ExecutionContext implements TruffleObject { /** * Initialize VM-wide static values. */ - public static void initialize(RCodeBuilder<RSyntaxNode> rAstBuilder, RRuntimeASTAccess rRuntimeASTAccess, RBuiltinLookup rBuiltinLookup, RForeignAccessFactory rForeignAccessFactory) { + public static void initializeGlobalState(RCodeBuilder<RSyntaxNode> rAstBuilder, RRuntimeASTAccess rRuntimeASTAccess, RBuiltinLookup rBuiltinLookup, RForeignAccessFactory rForeignAccessFactory) { RContext.astBuilder = rAstBuilder; RContext.runtimeASTAccess = rRuntimeASTAccess; RContext.builtinLookup = rBuiltinLookup; @@ -365,19 +398,25 @@ public final class RContext extends ExecutionContext implements TruffleObject { * could do this more dynamically with a registration process, perhaps driven by an annotation * processor, but the set is relatively small, so we just enumerate them here. */ - public REnvVars stateREnvVars; - public RProfile stateRProfile; - public ROptions.ContextStateImpl stateROptions; + public final REnvVars stateREnvVars; + public final RProfile stateRProfile; + public final StdConnections.ContextStateImpl stateStdConnections; + public final ROptions.ContextStateImpl stateROptions; public final REnvironment.ContextStateImpl stateREnvironment; public final RErrorHandling.ContextStateImpl stateRErrorHandling; public final ConnectionSupport.ContextStateImpl stateRConnection; - public final StdConnections.ContextStateImpl stateStdConnections; public final RRNG.ContextStateImpl stateRNG; - public final ContextState stateRFFI; public final RSerialize.ContextStateImpl stateRSerialize; public final LazyDBCache.ContextStateImpl stateLazyDBCache; public final InstrumentationState stateInstrumentation; public final ContextStateImpl stateInternalCode; + /** + * RFFI implementation state. Cannot be final as choice of FFI implementation is not made at the + * time the constructor is called. + */ + private ContextState stateRFFI; + + public final WeakHashMap<String, WeakReference<String>> stringMap = new WeakHashMap<>(); private ContextState[] contextStates() { return new ContextState[]{stateREnvVars, stateRProfile, stateROptions, stateREnvironment, stateRErrorHandling, stateRConnection, stateStdConnections, stateRNG, stateRFFI, stateRSerialize, @@ -392,6 +431,13 @@ public final class RContext extends ExecutionContext implements TruffleObject { return embedded; } + /** + * Sets the fields that do not depend on complex initialization. + * + * @param env values passed from {@link TruffleLanguage#createContext} + * @param instrumenter value passed from {@link TruffleLanguage#createContext} + * @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); if (initialInfo == null) { @@ -399,13 +445,34 @@ public final class RContext extends ExecutionContext implements TruffleObject { * This implies that FastR is being invoked initially from another Truffle language and * not via RCommand/RscriptCommand. */ - this.info = ContextInfo.create(new RStartParams(RCmdOptions.parseArguments(Client.R, new String[0], false), false), ContextKind.SHARE_NOTHING, null, - new DefaultConsoleHandler(env.in(), env.out())); + this.info = ContextInfo.create(new RStartParams(RCmdOptions.parseArguments(Client.R, new String[0], false), false), null, + ContextKind.SHARE_NOTHING, null, new DefaultConsoleHandler(env.in(), env.out())); } else { this.info = initialInfo; } this.initial = isInitial; + this.env = env; + this.stateREnvVars = REnvVars.newContextState(); + this.stateROptions = ROptions.ContextStateImpl.newContextState(stateREnvVars); + this.stateRProfile = RProfile.newContextState(stateREnvVars); + this.stateStdConnections = StdConnections.ContextStateImpl.newContextState(); + this.stateREnvironment = REnvironment.ContextStateImpl.newContextState(); + this.stateRErrorHandling = RErrorHandling.ContextStateImpl.newContextState(); + this.stateRConnection = ConnectionSupport.ContextStateImpl.newContextState(); + this.stateRNG = RRNG.ContextStateImpl.newContextState(); + this.stateRSerialize = RSerialize.ContextStateImpl.newContextState(); + this.stateLazyDBCache = LazyDBCache.ContextStateImpl.newContextState(); + this.stateInstrumentation = InstrumentationState.newContextState(instrumenter); + this.stateInternalCode = ContextStateImpl.newContextState(); + this.engine = RContext.getRRuntimeASTAccess().createEngine(this); + state.add(State.CONSTRUCTED); + } + /** + * Performs the real initialization of the context, invoked from + * {@link TruffleLanguage#initializeContext}. + */ + public RContext initializeContext() { // this must happen before engine activation in the code below if (info.getKind() == ContextKind.SHARE_NOTHING) { if (info.getParent() == null) { @@ -420,7 +487,6 @@ public final class RContext extends ExecutionContext implements TruffleObject { } } - this.env = env; if (info.getConsoleHandler() == null) { throw Utils.rSuicide("no console handler set"); } @@ -433,7 +499,6 @@ public final class RContext extends ExecutionContext implements TruffleObject { singleContextAssumption.invalidate(); } } - engine = RContext.getRRuntimeASTAccess().createEngine(this); /* * Activate the context by attaching the current thread and initializing the {@link @@ -444,26 +509,31 @@ public final class RContext extends ExecutionContext implements TruffleObject { * state creation but it is a finely balanced decision and risks incorrectly accessing the * parent state. */ - assert !active; - active = true; attachThread(); + state.add(State.ATTACHED); + if (!embedded) { doEnvOptionsProfileInitialization(); } - stateREnvironment = REnvironment.ContextStateImpl.newContext(this); - stateRErrorHandling = RErrorHandling.ContextStateImpl.newContext(this); - stateRConnection = ConnectionSupport.ContextStateImpl.newContext(this); - stateStdConnections = StdConnections.ContextStateImpl.newContext(this); - stateRNG = RRNG.ContextStateImpl.newContext(this); - stateRFFI = RFFIContextStateFactory.newContext(this); - stateRSerialize = RSerialize.ContextStateImpl.newContext(this); - stateLazyDBCache = LazyDBCache.ContextStateImpl.newContext(this); - stateInstrumentation = InstrumentationState.newContext(this, instrumenter); - stateInternalCode = ContextStateImpl.newContext(this); + + stateREnvironment.initialize(this); + stateRErrorHandling.initialize(this); + stateRConnection.initialize(this); + stateStdConnections.initialize(this); + stateRNG.initialize(this); + this.stateRFFI = RFFIContextStateFactory.newContextState().initialize(this); + + stateRFFI.initialize(this); + stateRSerialize.initialize(this); + stateLazyDBCache.initialize(this); + stateInstrumentation.initialize(this); + stateInternalCode.initialize(this); + state.add(State.INITIALIZED); if (!embedded) { validateContextStates(); engine.activate(stateREnvironment); + state.add(State.ACTIVE); } if (info.getKind() == ContextKind.SHARE_PARENT_RW) { @@ -475,33 +545,35 @@ public final class RContext extends ExecutionContext implements TruffleObject { // that methods package is loaded this.methodTableDispatchOn = info.getParent().methodTableDispatchOn; } - if (isInitial && !embedded) { + if (initial && !embedded) { RFFIFactory.getRFFI().getCallRFFI().setInteractive(isInteractive()); initialContextInitialized = true; } + return this; } /** * Factored out for embedded setup, where this initialization may be customized after the - * context is created but before VM really starts execution. + * context is initialized but before VM really starts execution. */ private void doEnvOptionsProfileInitialization() { - stateREnvVars = REnvVars.newContext(this); - stateROptions = ROptions.ContextStateImpl.newContext(this, stateREnvVars); - stateRProfile = RProfile.newContext(this, stateREnvVars); + stateREnvVars.initialize(this); + stateROptions.initialize(this); + stateRProfile.initialize(this); } public void completeEmbeddedInitialization() { doEnvOptionsProfileInitialization(); validateContextStates(); engine.activate(stateREnvironment); + state.add(State.ACTIVE); stateROptions.updateDotOptions(); initialContextInitialized = true; } private void validateContextStates() { - for (ContextState state : contextStates()) { - assert state != null; + for (ContextState contextState : contextStates()) { + assert contextState != null; } } @@ -517,17 +589,22 @@ public final class RContext extends ExecutionContext implements TruffleObject { /** * Destroy this context. */ - public void destroy() { - for (ContextState state : contextStates()) { - state.beforeDestroy(this); - } - if (info.getKind() == ContextKind.SHARE_PARENT_RW) { - info.getParent().sharedChild = null; - } - if (info.getParent() == null) { - threadLocalContext.set(null); - } else { - threadLocalContext.set(info.getParent()); + public synchronized void destroy() { + if (!state.contains(State.DESTROYED)) { + if (state.contains(State.INITIALIZED)) { + for (ContextState contextState : contextStates()) { + contextState.beforeDestroy(this); + } + } + if (info.getKind() == ContextKind.SHARE_PARENT_RW) { + info.getParent().sharedChild = null; + } + if (info.getParent() == null) { + threadLocalContext.set(null); + } else { + threadLocalContext.set(info.getParent()); + } + state = EnumSet.of(State.DESTROYED); } } @@ -547,11 +624,21 @@ public final class RContext extends ExecutionContext implements TruffleObject { return info.getKind(); } + @TruffleBoundary + public static RContext getThreadLocalInstance() { + return threadLocalContext.get(); + } + + @TruffleBoundary + public static void setThreadLocalInstance(RContext context) { + threadLocalContext.set(context); + } + @TruffleBoundary private static RContext getInstanceInternal() { RContext result = threadLocalContext.get(); assert result != null; - assert result.active; + assert result.state.contains(State.ATTACHED); return result; } @@ -584,29 +671,6 @@ public final class RContext extends ExecutionContext implements TruffleObject { return engine; } - public boolean isVisible() { - return resultVisible; - } - - public void setVisible(boolean v) { - if (!FastROptions.IgnoreVisibility.getBooleanValue()) { - /* - * Prevent printing the dummy expression used to force creation of initial context - */ - if (initialContextInitialized || !embedded) { - resultVisible = v; - } - } - } - - public void setVisible(RVisibility visibility) { - if (visibility == RVisibility.ON) { - setVisible(true); - } else if (visibility == RVisibility.OFF) { - setVisible(false); - } - } - public boolean isMethodTableDispatchOn() { return methodTableDispatchOn; } @@ -704,6 +768,10 @@ public final class RContext extends ExecutionContext implements TruffleObject { return info.getStartParams(); } + public String[] getEnvSettings() { + return info.getEnv(); + } + @Override public String toString() { return "context: " + info.getId(); @@ -755,10 +823,16 @@ public final class RContext extends ExecutionContext implements TruffleObject { throw new IllegalStateException("cannot access " + RContext.class.getSimpleName() + " via Truffle"); } - public static Closeable withinContext(RContext context) { + public interface RCloseable extends Closeable { + @Override + void close(); + } + + @TruffleBoundary + public static RCloseable withinContext(RContext context) { RContext oldContext = RContext.threadLocalContext.get(); RContext.threadLocalContext.set(context); - return new Closeable() { + return new RCloseable() { @Override public void close() { RContext.threadLocalContext.set(oldContext); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/AgentObjectSizeFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/AgentObjectSizeFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..7e303054edb4f818d2153f011bac4e37a0baebff --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/AgentObjectSizeFactory.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2016, 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; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.management.ManagementFactory; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; + +import javax.tools.ToolProvider; + +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.RObjectSize.IgnoreObjectHandler; +import com.oracle.truffle.r.runtime.data.RObjectSize.TypeCustomizer; + +/** + * Uses an instrumentation agent to get an accurate estimate of an objects size, plus reflection to + * aggregate the size of object-valued fields. Sharing is not handled in the general case, although + * some special cases are handed, such as the fact that {@link RNull} is a singleton. + * + * In order to satisfy the requirements of the Java instrumentation API, we have to load the agent + * from a jar file. The creation and loading is all orchestrated by this class. + */ +public class AgentObjectSizeFactory extends ObjectSizeFactory { + + private Map<Class<?>, ArrayList<Field>> objectFieldsMap = new HashMap<>(); + private static Map<Class<?>, TypeCustomizer> customizerMap = new HashMap<>(); // system wide + + public AgentObjectSizeFactory() { + if (!ObjSizeAgent.isInitialized()) { + try { + createAgentJar(); + } catch (Exception ex) { + // not available + Utils.rSuicide("failed to load ObjSizeAgent: " + ex.getMessage()); + } + } + } + + /** + * Adds the class file bytes for a given class to a JAR stream. + */ + static void add(JarOutputStream jar, Class<?> c) throws IOException { + String name = c.getName(); + String classAsPath = name.replace('.', '/') + ".class"; + jar.putNextEntry(new JarEntry(classAsPath)); + + InputStream stream = c.getClassLoader().getResourceAsStream(classAsPath); + + int nRead; + byte[] buf = new byte[1024]; + while ((nRead = stream.read(buf, 0, buf.length)) != -1) { + jar.write(buf, 0, nRead); + } + + jar.closeEntry(); + } + + protected void createAgentJar() throws Exception { + Manifest manifest = new Manifest(); + manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); + Attributes mainAttrs = manifest.getMainAttributes(); + mainAttrs.putValue("Agent-Class", ObjSizeAgent.class.getName()); + mainAttrs.putValue("Premain-Class", ObjSizeAgent.class.getName()); + + Path jar = Files.createTempFile("myagent", ".jar"); + try { + JarOutputStream jarStream = new JarOutputStream(new FileOutputStream(jar.toFile()), manifest); + add(jarStream, ObjSizeAgent.class); + jarStream.close(); + + loadAgent(jar); + } finally { + Files.deleteIfExists(jar); + } + } + + public static void loadAgent(Path agent) throws Exception { + String vmName = ManagementFactory.getRuntimeMXBean().getName(); + int p = vmName.indexOf('@'); + String pid = vmName.substring(0, p); + ClassLoader cl = ToolProvider.getSystemToolClassLoader(); + Class<?> c = Class.forName("com.sun.tools.attach.VirtualMachine", true, cl); + Method attach = c.getDeclaredMethod("attach", String.class); + Method loadAgent = c.getDeclaredMethod("loadAgent", String.class, String.class); + Object vm = attach.invoke(null, pid); + loadAgent.invoke(vm, agent.toString(), ""); + } + + @Override + public long getObjectSize(Object obj, IgnoreObjectHandler ignoreObjectHandler) { + return getObjectSize(obj, obj, ignoreObjectHandler); + } + + private long getObjectSize(Object rootObj, Object obj, IgnoreObjectHandler ignoreObjectHandler) { + try { + long basicSize = ObjSizeAgent.objectSize(obj); + long size = basicSize; + Class<?> klass = obj.getClass(); + if (klass.isArray() && !klass.getComponentType().isPrimitive()) { + for (int i = 0; i < Array.getLength(obj); i++) { + Object elem = Array.get(obj, i); + if (elem == null || isNa(elem)) { + continue; + } else { + size += getObjectSize(rootObj, elem, ignoreObjectHandler); + } + } + } else { + ArrayList<Field> objectFields = objectFieldsMap.get(klass); + if (objectFields == null) { + objectFields = new ArrayList<>(); + findObjectFields(obj.getClass(), objectFields); + objectFieldsMap.put(klass, objectFields); + } + for (Field objectField : objectFields) { + Object fieldObj = objectField.get(obj); + if (fieldObj == null || ignoreObjectHandler.ignore(rootObj, fieldObj)) { + continue; + } else { + TypeCustomizer typeCustomizer = getCustomizer(fieldObj.getClass()); + if (typeCustomizer == null) { + size += getObjectSize(rootObj, fieldObj, ignoreObjectHandler); + } else { + size += typeCustomizer.getObjectSize(fieldObj); + } + } + } + } + return size; + } catch (Throwable t) { + throw RInternalError.shouldNotReachHere(t); + } + + } + + private static boolean isNa(Object elem) { + String typeName = elem.getClass().getSimpleName(); + switch (typeName) { + case "Integer": + return RRuntime.isNA((int) elem); + case "Double": + return RRuntime.isNA((double) elem); + case "String": + return RRuntime.isNA((String) elem); + default: + return false; + } + } + + /** + * Walks the superclass hierarchy of {@code klass} and accumulates all object-valued fields in + * {@code objectFields}. + */ + private static void findObjectFields(Class<?> klass, ArrayList<Field> objectFields) { + if (klass != Object.class) { + findObjectFields(klass.getSuperclass(), objectFields); + Field[] fields = klass.getDeclaredFields(); + for (Field field : fields) { + Class<?> fieldClass = field.getType(); + if (fieldClass.isPrimitive()) { + continue; + } + int modifiers = field.getModifiers(); + if (Modifier.isStatic(modifiers)) { + continue; + } + // check for special case of an completely ignored type + if (getCustomizer(fieldClass) == RObjectSize.IGNORE) { + continue; + } + field.setAccessible(true); + objectFields.add(field); + } + } + } + + private static TypeCustomizer getCustomizer(Class<?> objClass) { + for (Map.Entry<Class<?>, TypeCustomizer> entry : customizerMap.entrySet()) { + if (entry.getKey().isAssignableFrom(objClass)) { + return entry.getValue(); + } + } + return null; + + } + + @Override + public void registerTypeCustomizer(Class<?> klass, TypeCustomizer typeCustomizer) { + customizerMap.put(klass, typeCustomizer); + } + +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryTracer.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryCopyTracer.java similarity index 58% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryTracer.java rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryCopyTracer.java index 05b5db6c2ab0659d63d734052b21dd3216ae1553..ecba6aeb9d75ef8362287e2d6d3da379319ec767 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryTracer.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryCopyTracer.java @@ -23,48 +23,58 @@ package com.oracle.truffle.r.runtime.data; +import java.util.Deque; +import java.util.concurrent.ConcurrentLinkedDeque; + import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; /** - * Helper for tracing memory related events. All implementors of {@link RAbstractVector} are - * expected to report to {@link MemoryTracer} and others can listen to them through {@link Listener} - * interface. Use method {@link #reportEvents()} to start the tracing. + * Helper for tracing memory copying events, as used by the {@code tracemem} bultin. All + * implementors of {@link RAbstractVector} are expected to report to {@link MemoryCopyTracer} and + * others can listen to them through {@link Listener} interface. Use method + * {@link #setTracingState(boolean)} to enable/disable the tracing. */ -public final class MemoryTracer { - private static Listener listener; - private static final Assumption noMemoryTracingAssumption = Truffle.getRuntime().createAssumption(); +public final class MemoryCopyTracer { + private static Deque<Listener> listeners = new ConcurrentLinkedDeque<>(); + private static boolean enabled; + + private static final Assumption noMemoryCopyTracingAssumption = Truffle.getRuntime().createAssumption("data copy tracing"); - private MemoryTracer() { + private MemoryCopyTracer() { // only static methods } /** - * Sets the listener of memory tracing events. For the time being there can only be one - * listener. This can be extended to an array should we need more listeners. + * Adds a listener of memory copying events. */ - public static void setListener(Listener newListener) { - listener = newListener; + public static void addListener(Listener listener) { + listeners.addLast(listener); } /** * After calling this method memory related events will be reported to the listener. This * invalidates global assumption and should be used with caution. */ - public static void reportEvents() { - noMemoryTracingAssumption.invalidate(); + public static void setTracingState(boolean newState) { + if (enabled != newState) { + if (newState) { + noMemoryCopyTracingAssumption.invalidate(); + } + enabled = newState; + } } /** * Reports copy event to the listener. If there are no traced objects, this should turn into - * no-op. TODO might be worth interposing on a change in {@code tracingState} to turn off the - * collection. + * no-op. */ public static void reportCopying(RAbstractVector source, RAbstractVector dest) { - if (!noMemoryTracingAssumption.isValid() && listener != null && RContext.getInstance().stateInstrumentation.getTracingState()) { - listener.reportCopying(source, dest); + if (!noMemoryCopyTracingAssumption.isValid() && enabled) { + for (Listener listener : listeners) { + listener.reportCopying(source, dest); + } } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjSizeAgent.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjSizeAgent.java new file mode 100644 index 0000000000000000000000000000000000000000..b6756248470bea75bf369bfd2859bd071c11de48 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjSizeAgent.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, 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; + +import java.lang.instrument.Instrumentation; + +/** + * This is agent class for object sizing. It has to be separate as it is loaded from a jar file. + * This implements the basic call to the JVM for the "struct" part of the object. + * {@link AgentObjectSizeFactory} handles the recursive sizing based on the field/array types. + * + */ +public class ObjSizeAgent { + private static Instrumentation instrumentation; + + public static void premain(@SuppressWarnings("unused") String agentArgs, Instrumentation inst) { + instrumentation = inst; + } + + public static void agentmain(@SuppressWarnings("unused") String agentArgs, Instrumentation inst) { + instrumentation = inst; + } + + public static long objectSize(Object obj) { + return instrumentation.getObjectSize(obj); + } + + static boolean isInitialized() { + return instrumentation != null; + } + +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..18a0cb472db916172c7386ab5e62fb9334a0552f --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjectSizeFactory.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016, 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; + +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"); + try { + theInstance = (ObjectSizeFactory) Class.forName(prop).newInstance(); + } catch (Exception ex) { + // CheckStyle: stop system..print check + System.err.println("Failed to instantiate class: " + prop); + } + } + + private static ObjectSizeFactory theInstance; + + public static ObjectSizeFactory getInstance() { + return theInstance; + } + + /** + * See {@link RObjectSize#getObjectSize}. + */ + public abstract long getObjectSize(Object obj, IgnoreObjectHandler ignoreObjectHandler); + + public abstract void registerTypeCustomizer(Class<?> klass, TypeCustomizer typeCustomizer); + +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/OutputAgentObjectSizeFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/OutputAgentObjectSizeFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..4d7279743c01e4518d20124db73a4676a5c65a0a --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/OutputAgentObjectSizeFactory.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, 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; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; + +import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.data.RObjectSize.IgnoreObjectHandler; + +/** + * A debugging tool, logs all calls to {@link #getObjectSize(Object, IgnoreObjectHandler)} to a + * file. + * + */ +public class OutputAgentObjectSizeFactory extends AgentObjectSizeFactory { + + private PrintWriter printWriter; + + public OutputAgentObjectSizeFactory() { + try { + printWriter = new PrintWriter(new FileWriter(Utils.getLogPath("fastr_objectsize.log").toString())); + } catch (IOException ex) { + Utils.rSuicide(ex.getMessage()); + } + + } + + @Override + public long getObjectSize(Object obj, IgnoreObjectHandler ignoreObjectHandler) { + long size = super.getObjectSize(obj, ignoreObjectHandler); + printWriter.printf("%s: %d\n", obj.getClass().getSimpleName(), (int) size); + printWriter.flush(); + return size; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributes.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributes.java index 69956311d4b3aa3156ec465a70e3fa9fceb015b0..b2c771cdee0e2be25ba77abd9b978c62d04e9d00 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributes.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributes.java @@ -23,15 +23,16 @@ package com.oracle.truffle.r.runtime.data; import java.util.Arrays; +import java.util.Deque; import java.util.Iterator; import java.util.NoSuchElementException; +import java.util.concurrent.ConcurrentLinkedDeque; 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.CompilerDirectives.ValueType; -import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.runtime.RPerfStats; +import com.oracle.truffle.api.utilities.CyclicAssumption; /** * Provides the generic mechanism for associating attributes with a R object. It does no special @@ -71,12 +72,14 @@ public final class RAttributes implements Iterable<RAttributes.RAttribute> { } } - private static final ConditionProfile statsProfile = ConditionProfile.createBinaryProfile(); - public static RAttributes create() { return new RAttributes(); } + public static RAttributes create(RAttributes attr) { + return new RAttributes(attr); + } + public static RAttributes createInitialized(String[] names, Object[] values) { return new RAttributes(names, values); } @@ -98,8 +101,8 @@ public final class RAttributes implements Iterable<RAttributes.RAttribute> { */ RAttributes() { - if (statsProfile.profile(stats != null)) { - stats.init(); + if (AttributeTracer.enabled) { + AttributeTracer.reportAttributeChange(AttributeTracer.Change.CREATE, this, null); } } @@ -130,6 +133,7 @@ public final class RAttributes implements Iterable<RAttributes.RAttribute> { public void put(String name, Object value) { assert isInterned(name); int pos = find(name); + int spos = pos; if (pos == -1) { ensureFreeSpace(); pos = size++; @@ -139,8 +143,8 @@ public final class RAttributes implements Iterable<RAttributes.RAttribute> { // assert value == null || !(value instanceof RShareable) || !((RShareable) // value).isTemporary(); values[pos] = value; - if (statsProfile.profile(stats != null)) { - stats.update(this); + if (AttributeTracer.enabled) { + AttributeTracer.reportAttributeChange(spos == -1 ? AttributeTracer.Change.ADD : AttributeTracer.Change.UPDATE, this, name); } } @@ -149,6 +153,9 @@ public final class RAttributes implements Iterable<RAttributes.RAttribute> { names = Arrays.copyOf(names, (size + 1) * 2); values = Arrays.copyOf(values, (size + 1) * 2); assert names.length == values.length; + if (AttributeTracer.enabled) { + AttributeTracer.reportAttributeChange(AttributeTracer.Change.GROW, this, names.length); + } } } @@ -202,6 +209,9 @@ public final class RAttributes implements Iterable<RAttributes.RAttribute> { } names[size] = null; values[size] = null; + if (AttributeTracer.enabled) { + AttributeTracer.reportAttributeChange(AttributeTracer.Change.REMOVE, this, name); + } } } @@ -267,55 +277,64 @@ public final class RAttributes implements Iterable<RAttributes.RAttribute> { throw new NoSuchElementException(); } - // Performance analysis - - @CompilationFinal private static PerfHandler stats; - - static { - RPerfStats.register(new PerfHandler()); + public void setSize(int size) { + this.size = size; } - /** - * Collects data on the maximum size of the attribute set. So only interested in adding not - * removing attributes. - */ - private static class PerfHandler implements RPerfStats.Handler { - private static final RPerfStats.Histogram hist = new RPerfStats.Histogram(5); + public static final class AttributeTracer { + private static Deque<Listener> listeners = new ConcurrentLinkedDeque<>(); + @CompilationFinal private static boolean enabled; + + private static final CyclicAssumption noAttributeTracingAssumption = new CyclicAssumption("data copying"); - @TruffleBoundary - void init() { - hist.inc(0); + private AttributeTracer() { + // only static methods } - @TruffleBoundary - void update(RAttributes attr) { - // incremented size by 1 - int s = attr.size(); - int effectivePrevSize = hist.effectiveBucket(s - 1); - int effectiveSizeNow = hist.effectiveBucket(s); - hist.dec(effectivePrevSize); - hist.inc(effectiveSizeNow); + /** + * Adds a listener of attribute events. + */ + public static void addListener(Listener listener) { + listeners.addLast(listener); } - @Override - public void initialize(String optionText) { - stats = this; + /** + * After calling this method attribute related events will be reported to the listener. This + * invalidates global assumption and should be used with caution. + */ + public static void setTracingState(boolean newState) { + if (enabled != newState) { + noAttributeTracingAssumption.invalidate(); + enabled = newState; + } } - @Override - public String getName() { - return "attributes"; + public enum Change { + CREATE, + ADD, + UPDATE, + REMOVE, + GROW + } + public static void reportAttributeChange(Change change, RAttributes attrs, Object value) { + if (enabled) { + for (Listener listener : listeners) { + listener.reportAttributeChange(change, attrs, value); + } + } } - @Override - public void report() { - RPerfStats.out().printf("RAttributes: %d, max size %d%n", hist.getTotalCount(), hist.getMaxSize()); - hist.report(); + public interface Listener { + /** + * Reports attribute events to the listener. If there are no traced objects, this should + * turn into no-op. {@code valuer} depends on the value of {@code change}. For + * {@code CREATE} it is {@code null}, for {@code ADD,UPDATE, REMOVE} it is the + * {@code String} name of the attribute and for {@code GROW} it is the (new) size. + */ + void reportAttributeChange(Change change, RAttributes attrs, Object value); } - } - public void setSize(int size) { - this.size = size; } + } 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 1bfe70252de40c3162543da9ef30c416b27154b2..7f5c274b1b9251a317aa29aa46350dc5af3d7264 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 @@ -68,7 +68,7 @@ public final class RComplex extends RScalarVector implements RAbstractComplexVec @Override public RComplexVector materialize() { RComplexVector result = RDataFactory.createComplexVectorFromScalar(this); - MemoryTracer.reportCopying(this, result); + MemoryCopyTracer.reportCopying(this, result); return result; } @@ -95,7 +95,7 @@ public final class RComplex extends RScalarVector implements RAbstractComplexVec @TruffleBoundary public String toString() { CompilerAsserts.neverPartOfCompilation(); - return toString(RRuntime.doubleToString(realPart), RRuntime.doubleToString(imaginaryPart)); + return toString(Double.toString(realPart), Double.toString(imaginaryPart)); } public String toString(String realPartString, String imaginaryPartString) { 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 e94bd445cc3b6d629053f86da551dbab6deea2bf..585753ac6fe8858cc44a94668e42df1ff2c63b24 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 @@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; -public final class RComplexVector extends RVector implements RAbstractComplexVector { +public final class RComplexVector extends RVector<double[]> implements RAbstractComplexVector { public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Complex.getClazz()); @@ -102,7 +102,7 @@ public final class RComplexVector extends RVector implements RAbstractComplexVec @Override public String toString() { - return toString(i -> RRuntime.complexToString(getDataAt(i))); + return toString(i -> getDataAt(i).toString()); } @Override @@ -117,51 +117,25 @@ public final class RComplexVector extends RVector implements RAbstractComplexVec return true; } + @Override public double[] getDataCopy() { - double[] copy = new double[data.length]; - System.arraycopy(data, 0, copy, 0, data.length); - return copy; + return Arrays.copyOf(data, data.length); } /** * Intended for external calls where a copy is not needed. WARNING: think carefully before using * this method rather than {@link #getDataCopy()}. */ + @Override public double[] getDataWithoutCopying() { return data; } - /** - * Return vector data (copying if necessary) that's guaranteed not to be shared with any other - * vector instance (but maybe non-temporary in terms of vector's sharing mode). - * - * @return vector data - */ - public double[] getDataNonShared() { - return isShared() ? getDataCopy() : getDataWithoutCopying(); - - } - - /** - * Return vector data (copying if necessary) that's guaranteed to be "fresh" (temporary in terms - * of vector sharing mode). - * - * @return vector data - */ - public double[] getDataTemp() { - return isTemporary() ? getDataWithoutCopying() : getDataCopy(); - } - @Override public RComplexVector copyWithNewDimensions(int[] newDimensions) { return RDataFactory.createComplexVector(data, isComplete(), newDimensions); } - @Override - protected String getDataAtAsString(int index) { - return getDataAt(index).toString(); - } - private RComplexVector updateDataAt(int i, RComplex right, NACheck rightNACheck) { assert !this.isShared(); int index = i << 1; 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 6131402db4e6ecb0b06453b5f497cb289ce5314e..d7986b1a56653ab5d8228188ab699b3b141b2b10 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 @@ -23,8 +23,8 @@ package com.oracle.truffle.r.runtime.data; import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; +import java.util.Deque; +import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.atomic.AtomicInteger; import com.oracle.truffle.api.Assumption; @@ -32,28 +32,21 @@ 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.MaterializedFrame; -import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.utilities.CyclicAssumption; import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RPerfStats; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.data.RPromise.Closure; import com.oracle.truffle.r.runtime.data.RPromise.EagerFeedback; import com.oracle.truffle.r.runtime.data.RPromise.PromiseState; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; -import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; public final class RDataFactory { - /** - * Profile for creation tracing; must precede following declarations. - */ - private static final ConditionProfile statsProfile = ConditionProfile.createBinaryProfile(); - public static final boolean INCOMPLETE_VECTOR = false; public static final boolean COMPLETE_VECTOR = true; @@ -387,8 +380,16 @@ public final class RDataFactory { return traceDataCreated(new RList(data, newDimensions, names)); } - public static RExpression createExpression(RList list) { - return traceDataCreated(new RExpression(list)); + public static RExpression createExpression(Object[] data, int[] newDimensions) { + return traceDataCreated(new RExpression(data, newDimensions, null)); + } + + public static RExpression createExpression(Object[] data, RStringVector names) { + return traceDataCreated(new RExpression(data, null, names)); + } + + public static RExpression createExpression(Object[] data) { + return traceDataCreated(new RExpression(data, null, null)); } public static RSymbol createSymbol(String name) { @@ -404,7 +405,7 @@ public final class RDataFactory { return createSymbol(name.intern()); } - public static RLanguage createLanguage(RNode rep) { + public static RLanguage createLanguage(RBaseNode rep) { return traceDataCreated(new RLanguage(rep)); } @@ -418,7 +419,7 @@ public final class RDataFactory { return traceDataCreated(new RPromise(state, closure, argumentValue)); } - public static Object createEvaluatedPromise(Closure closure, Object value) { + public static RPromise createEvaluatedPromise(Closure closure, Object value) { return traceDataCreated(new RPromise(PromiseState.Explicit, closure, value)); } @@ -471,14 +472,17 @@ public final class RDataFactory { private static final AtomicInteger environmentCount = new AtomicInteger(); + @TruffleBoundary public static REnvironment createInternalEnv() { return traceDataCreated(new REnvironment.NewEnv(RRuntime.createNonFunctionFrame("<internal-env-" + environmentCount.incrementAndGet() + ">"), REnvironment.UNNAMED)); } + @TruffleBoundary public static REnvironment.NewEnv createNewEnv(String name) { return traceDataCreated(new REnvironment.NewEnv(RRuntime.createNonFunctionFrame("<new-env-" + environmentCount.incrementAndGet() + ">"), name)); } + @TruffleBoundary public static REnvironment createNewEnv(String name, boolean hashed, int initialSize) { REnvironment.NewEnv env = new REnvironment.NewEnv(RRuntime.createNonFunctionFrame("<new-env-" + environmentCount.incrementAndGet() + ">"), name); env.setHashed(hashed); @@ -498,65 +502,50 @@ public final class RDataFactory { return traceDataCreated(new RExternalPtr(value, tag, RNull.instance)); } - @CompilationFinal private static PerfHandler stats; + /* + * Support for collecting information on allocations in this class. Rprofmem/Rprof register a + * listener when active which, when memory profiling is enabled, is called with the object being + * allocated. Owing to the use of the Assumption, there should be no overhead when disabled. + */ - private static <T> T traceDataCreated(T data) { - if (statsProfile.profile(stats != null)) { - stats.record(data); - } - return data; - } + private static Deque<Listener> listeners = new ConcurrentLinkedDeque<>(); + @CompilationFinal private static boolean enabled; + private static final CyclicAssumption noAllocationTracingAssumption = new CyclicAssumption("data allocation"); - static { - RPerfStats.register(new PerfHandler()); + public static void setTracingState(boolean newState) { + if (enabled != newState) { + noAllocationTracingAssumption.invalidate(); + enabled = newState; + } } - private static class PerfHandler implements RPerfStats.Handler { - private static Map<Class<?>, RPerfStats.Histogram> histMap; - - @TruffleBoundary - void record(Object data) { - Class<?> klass = data.getClass(); - boolean isBounded = data instanceof RAbstractVector; - RPerfStats.Histogram hist = histMap.get(klass); - if (hist == null) { - hist = new RPerfStats.Histogram(isBounded ? 10 : 1); - histMap.put(klass, hist); + private static <T> T traceDataCreated(T data) { + if (enabled) { + for (Listener listener : listeners) { + listener.reportAllocation((RTypedValue) data); } - int length = isBounded ? ((RAbstractVector) data).getLength() : 0; - hist.inc(length); - } - - @Override - public void initialize(String optionData) { - stats = this; - histMap = new HashMap<>(); } + return data; + } - @Override - public String getName() { - return "datafactory"; - } + public interface Listener { + /** + * Invoked when an instance of an {@link RTypedValue} is created. Note that the initial + * state of the complex objects, i.e., those with additional {@code Object} subclass fields, + * which may also be {@link RTypedValue} instances is undefined other than by inspection. A + * listener that computes the "size" of an object must take into account that + * {@link RTypedValue} instances passed to a {@code createXXX} method will already have been + * reported, but other data such as {@code int[]} instances for array dimensions will not. + */ + void reportAllocation(RTypedValue data); + } - @Override - public void report() { - RPerfStats.out().println("Scalar types"); - for (Map.Entry<Class<?>, RPerfStats.Histogram> entry : histMap.entrySet()) { - RPerfStats.Histogram hist = entry.getValue(); - if (hist.numBuckets() == 1) { - RPerfStats.out().printf("%s: %d%n", entry.getKey().getSimpleName(), hist.getTotalCount()); - } - } - RPerfStats.out().println(); - RPerfStats.out().println("Vector types"); - for (Map.Entry<Class<?>, RPerfStats.Histogram> entry : histMap.entrySet()) { - RPerfStats.Histogram hist = entry.getValue(); - if (hist.numBuckets() > 1) { - RPerfStats.out().printf("%s: %d, max size %d%n", entry.getKey().getSimpleName(), hist.getTotalCount(), hist.getMaxSize()); - entry.getValue().report(); - } - } - RPerfStats.out().println(); - } + /** + * Sets the listener of memory tracing events. For the time being there can only be one + * listener. This can be extended to an array should we need more listeners. + */ + public static void addListener(Listener listener) { + listeners.addLast(listener); } + } 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 096356c36aaf5031ea8b85166e820cfbd7d960b5..2caf812292e1c4270b619fe81165d7e1066aa7b2 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 @@ -90,7 +90,7 @@ public final class RDouble extends RScalarVector implements RAbstractDoubleVecto @Override public RDoubleVector materialize() { RDoubleVector result = RDataFactory.createDoubleVectorFromScalar(getValue()); - MemoryTracer.reportCopying(this, result); + MemoryCopyTracer.reportCopying(this, result); return result; } 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 c542875fa7f26d8e6b64219f65df90db26b6db82..be3aaec3c9c8f8b69eb6a5403c0050cbbb345ed9 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 @@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; -public final class RDoubleVector extends RVector implements RAbstractDoubleVector { +public final class RDoubleVector extends RVector<double[]> implements RAbstractDoubleVector { public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Double.getClazz()); @@ -109,7 +109,7 @@ public final class RDoubleVector extends RVector implements RAbstractDoubleVecto @Override public String toString() { - return toString(i -> RRuntime.doubleToString(getDataAt(i))); + return toString(i -> Double.toString(getDataAt(i))); } @Override @@ -129,51 +129,25 @@ public final class RDoubleVector extends RVector implements RAbstractDoubleVecto return data[i]; } + @Override public double[] getDataCopy() { - double[] copy = new double[data.length]; - System.arraycopy(data, 0, copy, 0, data.length); - return copy; + return Arrays.copyOf(data, data.length); } /** * Intended for external calls where a copy is not needed. WARNING: think carefully before using * this method rather than {@link #getDataCopy()}. */ + @Override public double[] getDataWithoutCopying() { return data; } - /** - * Return vector data (copying if necessary) that's guaranteed not to be shared with any other - * vector instance (but maybe non-temporary in terms of vector's sharing mode). - * - * @return vector data - */ - public double[] getDataNonShared() { - return isShared() ? getDataCopy() : getDataWithoutCopying(); - - } - - /** - * Return vector data (copying if necessary) that's guaranteed to be "fresh" (temporary in terms - * of vector sharing mode). - * - * @return vector data - */ - public double[] getDataTemp() { - return isTemporary() ? getDataWithoutCopying() : getDataCopy(); - } - @Override public RDoubleVector copyWithNewDimensions(int[] newDimensions) { return RDataFactory.createDoubleVector(data, isComplete(), newDimensions); } - @Override - protected String getDataAtAsString(int index) { - return RRuntime.doubleToString(data[index]); - } - public RDoubleVector updateDataAt(int i, double right, NACheck valueNACheck) { assert !this.isShared(); data[i] = right; 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 db152ea75c480c947523c6de0859610428cea933..8c434b5af633b287c8aed8345d2e8fe4b6625689 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 @@ -22,19 +22,19 @@ */ package com.oracle.truffle.r.runtime.data; -import com.oracle.truffle.r.runtime.RRuntime; +import java.util.Arrays; + import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -public class RExpression implements RShareable, RAbstractContainer { +public class RExpression extends RListBase implements RAbstractVector { private static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Expression.getClazz()); - private final RList data; + public String elementNamePrefix; - public RExpression(RList data) { - this.data = data; + RExpression(Object[] data, int[] dims, RStringVector names) { + super(data, dims, names); } @Override @@ -42,197 +42,53 @@ public class RExpression implements RShareable, RAbstractContainer { return RType.Expression; } - public RList getList() { - return data; - } - - public Object getDataAt(int index) { - return data.getDataAt(index); - } - - @Override - public RAttributes initAttributes() { - return data.initAttributes(); - } - - @Override - public final void initAttributes(RAttributes newAttributes) { - data.initAttributes(newAttributes); - } - - @Override - public final void setAttr(String name, Object value) { - data.setAttr(name, value); - } - - @Override - public Object getAttr(RAttributeProfiles attrProfiles, String name) { - return data.getAttr(attrProfiles, name); - } - - @Override - public RAttributes getAttributes() { - return data.getAttributes(); - } - - @Override - public final void resetAllAttributes(boolean nullify) { - data.resetAllAttributes(nullify); - } - - @Override - public boolean isComplete() { - return data.isComplete(); - } - - @Override - public int getLength() { - return data.getLength(); - } - - @Override - public RAbstractContainer resize(int size) { - return data.resize(size); - } - - @Override - public boolean hasDimensions() { - return data.hasDimensions(); - } - - @Override - public int[] getDimensions() { - return data.getDimensions(); - } - - @Override - public void setDimensions(int[] newDimensions) { - data.setDimensions(newDimensions); - } - - @Override - public Class<?> getElementClass() { - return RExpression.class; - } - - @Override - public Object getDataAtAsObject(int index) { - return data.getDataAtAsObject(index); - } - @Override - public RStringVector getNames(RAttributeProfiles attrProfiles) { - return data.getNames(attrProfiles); - } - - @Override - public void setNames(RStringVector newNames) { - data.setNames(newNames); - } - - @Override - public RList getDimNames(RAttributeProfiles attrProfiles) { - return data.getDimNames(); - } - - @Override - public void setDimNames(RList newDimNames) { - data.setDimNames(newDimNames); - } - - @Override - public Object getRowNames(RAttributeProfiles attrProfiles) { - return data.getRowNames(); + public RVector<?> materialize() { + return this; } @Override - public void setRowNames(RAbstractVector rowNames) { - data.setRowNames(rowNames); + protected RExpression internalCopy() { + return new RExpression(Arrays.copyOf(data, data.length), dimensions, null); } @Override - public final RStringVector getClassHierarchy() { - RStringVector v = (RStringVector) data.getAttr(RRuntime.CLASS_ATTR_KEY); - if (v == null) { - return getImplicitClass(); - } else { - return v; + protected RExpression internalDeepCopy() { + // TOOD: only used for nested list updates, but still could be made faster (through a + // separate AST node?) + RExpression listCopy = new RExpression(Arrays.copyOf(data, data.length), dimensions, null); + for (int i = 0; i < listCopy.getLength(); i++) { + Object el = listCopy.getDataAt(i); + if (el instanceof RVector) { + Object elCopy = ((RVector<?>) el).deepCopy(); + listCopy.updateDataAt(i, elCopy, null); + } } + return listCopy; } @Override - public RStringVector getImplicitClass() { - return implicitClassHeader; - } - - @Override - public boolean isObject(RAttributeProfiles attrProfiles) { - return false; - } - - @Override - public boolean isTemporary() { - return data.isTemporary(); - } - - @Override - public boolean isShared() { - return data.isShared(); + public RExpression createEmptySameType(int newLength, boolean newIsComplete) { + return RDataFactory.createExpression(new Object[newLength]); } @Override - public void incRefCount() { - data.incRefCount(); + public RExpression copyWithNewDimensions(int[] newDimensions) { + return RDataFactory.createExpression(data, newDimensions); } @Override - public void decRefCount() { - data.decRefCount(); + protected RExpression internalCopyResized(int size, boolean fillNA) { + return RDataFactory.createExpression(copyResizedData(size, fillNA)); } @Override - public boolean isSharedPermanent() { - return data.isSharedPermanent(); - } - - @Override - public RShareable makeSharedPermanent() { - return data.makeSharedPermanent(); - } - - @Override - public RShareable getNonShared() { - RList newData = (RList) data.getNonShared(); - return newData == data ? this : RDataFactory.createExpression(newData); - } - - @Override - public RExpression copy() { - return RDataFactory.createExpression((RList) data.copy()); - } - - @Override - public RShareable materializeToShareable() { - return this; - } - - @Override - public RAbstractContainer setClassAttr(RStringVector classAttr) { - return data.setClassAttr(classAttr); - } - - @Override - public String toString() { - return String.format("RExpression(data=%s)", data); - } - - @Override - public int getTypedValueInfo() { - return data.getTypedValueInfo(); + public RStringVector getImplicitClass() { + return getClassHierarchyHelper(implicitClassHeader); } @Override - public void setTypedValueInfo(int value) { - data.setTypedValueInfo(value); + public void setNA(Object store, int index) { + setDataAt(store, index, RNull.instance); } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java index 38be9af40f36164d56587af36bcc06e2975c6444..3d7371741262d164a0cdcfba4648e9c701d8d472 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java @@ -35,7 +35,7 @@ public final class RFactor { * Helper method to get 'levels' of a factor. However, all the invocations of this method should * be replaced with FactorNodes.GetLevel in the future. */ - public static RVector getLevels(RAbstractIntVector factor) { + public static RVector<?> getLevels(RAbstractIntVector factor) { return getLevelsImpl(factor.getAttr(RRuntime.LEVELS_ATTR_KEY)); } @@ -43,12 +43,12 @@ public final class RFactor { * Helper method to get 'levels' of a factor with profile. However, all the invocations of this * method should be replaced with FactorNodes.GetLevel in the future. */ - public static RVector getLevels(RAttributeProfiles profile, RAbstractIntVector factor) { + public static RVector<?> getLevels(RAttributeProfiles profile, RAbstractIntVector factor) { return getLevelsImpl(factor.getAttr(profile, RRuntime.LEVELS_ATTR_KEY)); } - private static RVector getLevelsImpl(Object attr) { - // convert scalar to RVector if necessary - return attr instanceof RVector ? (RVector) attr : (RVector) RRuntime.asAbstractVector(attr); + private static RVector<?> getLevelsImpl(Object attr) { + // convert scalar to RVector<?>if necessary + return attr instanceof RVector ? (RVector<?>) attr : (RVector<?>) RRuntime.asAbstractVector(attr); } } 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 74e182b9cee2de064c08e037eea0ad49440e66dd..c1a53a35f6249ef756e29261fc3d67d3332fd8d7 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 @@ -33,7 +33,7 @@ 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; -public final class RIntVector extends RVector implements RAbstractIntVector { +public final class RIntVector extends RVector<int[]> implements RAbstractIntVector { public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Integer.getClazz()); @@ -114,7 +114,7 @@ public final class RIntVector extends RVector implements RAbstractIntVector { @Override public String toString() { - return toString(i -> RRuntime.doubleToString(getDataAt(i))); + return toString(i -> Double.toString(getDataAt(i))); } @Override @@ -129,6 +129,7 @@ public final class RIntVector extends RVector implements RAbstractIntVector { return true; } + @Override public int[] getDataCopy() { return Arrays.copyOf(data, data.length); } @@ -137,41 +138,16 @@ public final class RIntVector extends RVector implements RAbstractIntVector { * Intended for external calls where a copy is not needed. WARNING: think carefully before using * this method rather than {@link #getDataCopy()}. */ + @Override public int[] getDataWithoutCopying() { return data; } - /** - * Return vector data (copying if necessary) that's guaranteed not to be shared with any other - * vector instance (but maybe non-temporary in terms of vector's sharing mode). - * - * @return vector data - */ - public int[] getDataNonShared() { - return isShared() ? getDataCopy() : getDataWithoutCopying(); - - } - - /** - * Return vector data (copying if necessary) that's guaranteed to be "fresh" (temporary in terms - * of vector sharing mode). - * - * @return vector data - */ - public int[] getDataTemp() { - return isTemporary() ? getDataWithoutCopying() : getDataCopy(); - } - @Override public RIntVector copyWithNewDimensions(int[] newDimensions) { return RDataFactory.createIntVector(data, isComplete(), newDimensions); } - @Override - protected String getDataAtAsString(int index) { - return RRuntime.intToString(this.getDataAt(index)); - } - public RIntVector updateDataAt(int i, int right, NACheck valueNACheck) { assert !this.isShared(); data[i] = right; 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 075d9ee51126ff8bd297ebffb5b11bed48055b13..33ba1ebd83bac82664770babb137ec2908cf5148 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 @@ -88,7 +88,7 @@ public final class RInteger extends RScalarVector implements RAbstractIntVector @Override public RIntVector materialize() { RIntVector result = RDataFactory.createIntVectorFromScalar(value); - MemoryTracer.reportCopying(this, result); + MemoryCopyTracer.reportCopying(this, result); return result; } 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 fab7bda0eb01d0a97daf70dc11b3785f85957e33..6621d6063dffb62b98380ae2a559dd604e519d77 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 @@ -30,7 +30,6 @@ import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; 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; /** * Denotes an (unevaluated) R language element. It is equivalent to a LANGSXP value in GnuR. It @@ -47,7 +46,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode; * */ @ValueType -public class RLanguage extends RSharingAttributeStorage implements RAbstractContainer, RAttributable, RShareable { +public class RLanguage extends RSharingAttributeStorage implements RAbstractContainer { /* * Used for RLanguage construction from separate AST components. @@ -59,6 +58,7 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont } private RBaseNode rep; + private RPairList list; private String callLHSName; /** @@ -66,21 +66,43 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont */ private int length = -1; - RLanguage(RNode rep) { + RLanguage(RBaseNode rep) { this.rep = rep; } - private RLanguage(RNode rep, int length) { + private RLanguage(RBaseNode rep, int length) { this.rep = rep; this.length = length; } + public static Object fromList(Object o, RLanguage.RepType type) { + RList l; + if (o instanceof RPairList) { + l = ((RPairList) o).toRList(); + } else { + l = (RList) o; + } + return RContext.getRRuntimeASTAccess().fromList(l, type); + } + public RBaseNode getRep() { + if (list != null) { + // we could rest rep but we keep it around to remember type of the language object + assert rep != null; + // list must be reset before rep type is obtained + RPairList oldList = this.list; + this.list = null; + RLanguage newLang = (RLanguage) fromList(oldList, RContext.getRRuntimeASTAccess().getRepType(this)); + this.rep = newLang.rep; + this.length = newLang.length; + this.attributes = newLang.attributes; + } return rep; } public void setRep(RBaseNode rep) { this.rep = rep; + this.list = null; } public String getCallLHSName() { @@ -103,10 +125,15 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont @Override public int getLength() { - if (length < 0) { - length = RContext.getRRuntimeASTAccess().getLength(this); + // if list representation is present, it takes priority as it might have been updated + if (list == null) { + if (length < 0) { + length = RContext.getRRuntimeASTAccess().getLength(this); + } + return length; + } else { + return list.getLength(); } - return length; } @Override @@ -144,46 +171,62 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont @Override public Object getDataAtAsObject(int index) { - return RContext.getRRuntimeASTAccess().getDataAtAsObject(this, index); + if (list == null) { + return RContext.getRRuntimeASTAccess().getDataAtAsObject(this, index); + } else { + return list.getDataAtAsObject(index); + } } @Override public RStringVector getNames(RAttributeProfiles attrProfiles) { - /* - * "names" for a language object is a special case, that is applicable to calls and returns - * the names of the actual arguments, if any. E.g. f(x=1, 3) would return c("", "x", ""). - * GnuR defines it as returning the "tag" values on the pairlist that represents the call. - * Well, we don't have a pairlist, (we could get one by serializing the expression), so we - * do it by AST walking. - */ - RStringVector names = RContext.getRRuntimeASTAccess().getNames(this); - return names; + if (list == null) { + /* + * "names" for a language object is a special case, that is applicable to calls and + * returns the names of the actual arguments, if any. E.g. f(x=1, 3) would return c("", + * "x", ""). GnuR defines it as returning the "tag" values on the pairlist that + * represents the call. Well, we don't have a pairlist, (we could get one by serializing + * the expression), so we do it by AST walking. + */ + RStringVector names = RContext.getRRuntimeASTAccess().getNames(this); + return names; + } else { + return list.getNames(attrProfiles); + } } @Override public void setNames(RStringVector newNames) { - /* See getNames */ - RContext.getRRuntimeASTAccess().setNames(this, newNames); + if (list == null) { + /* See getNames */ + RContext.getRRuntimeASTAccess().setNames(this, newNames); + } else { + list.setNames(newNames); + } } @Override public RList getDimNames(RAttributeProfiles attrProfiles) { - return (RList) getAttr(attrProfiles, RRuntime.DIMNAMES_ATTR_KEY); + RAttributable attr = list == null ? this : list; + return (RList) attr.getAttr(attrProfiles, RRuntime.DIMNAMES_ATTR_KEY); } @Override public void setDimNames(RList newDimNames) { - setAttr(RRuntime.DIMNAMES_ATTR_KEY, newDimNames); + RAttributable attr = list == null ? this : list; + attr.setAttr(RRuntime.DIMNAMES_ATTR_KEY, newDimNames); } @Override public Object getRowNames(RAttributeProfiles attrProfiles) { - return getAttr(attrProfiles, RRuntime.ROWNAMES_ATTR_KEY); + RAttributable attr = list == null ? this : list; + return attr.getAttr(attrProfiles, RRuntime.ROWNAMES_ATTR_KEY); } @Override public void setRowNames(RAbstractVector rowNames) { - setAttr(RRuntime.ROWNAMES_ATTR_KEY, rowNames); + RAttributable attr = list == null ? this : list; + attr.setAttr(RRuntime.ROWNAMES_ATTR_KEY, rowNames); } @Override @@ -191,14 +234,9 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont return RDataFactory.createStringVector(RRuntime.CLASS_LANGUAGE); } - @Override - public boolean isObject(RAttributeProfiles attrProfiles) { - return false; - } - @Override public RLanguage copy() { - RLanguage l = new RLanguage((RNode) getRep(), this.length); + RLanguage l = new RLanguage(getRep(), this.length); if (this.attributes != null) { l.attributes = attributes.copy(); } @@ -210,4 +248,21 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont public String toString() { return String.format("RLanguage(rep=%s)", getRep()); } + + public RPairList getPairList() { + if (list == null) { + Object obj = RNull.instance; + for (int i = getLength() - 1; i >= 0; i--) { + Object element = RContext.getRRuntimeASTAccess().getDataAtAsObject(this, i); + obj = RDataFactory.createPairList(element, obj); + } + // names have to be taken before list is assigned + RStringVector names = RContext.getRRuntimeASTAccess().getNames(this); + list = (RPairList) obj; + if (names != null) { + list.setNames(names); + } + } + return list; + } } 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 c97e5a73d88d9290e5597a439ec0b73d82d13a7e..dd97f6ea0d42c018c7089d82c5b38b1a1609dddd 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,10 +25,11 @@ package com.oracle.truffle.r.runtime.data; import java.util.Arrays; import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; -public final class RList extends RListBase { +public final class RList extends RListBase implements RAbstractListVector { - private static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.List.getClazz()); + public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.List.getClazz()); public String elementNamePrefix; @@ -47,14 +48,14 @@ public final class RList extends RListBase { } @Override - protected RVector internalDeepCopy() { + protected RList internalDeepCopy() { // TOOD: only used for nested list updates, but still could be made faster (through a // separate AST node?) RList listCopy = new RList(Arrays.copyOf(data, data.length), dimensions, null); for (int i = 0; i < listCopy.getLength(); i++) { Object el = listCopy.getDataAt(i); if (el instanceof RVector) { - Object elCopy = ((RVector) el).deepCopy(); + Object elCopy = ((RVector<?>) el).deepCopy(); listCopy.updateDataAt(i, elCopy, null); } } @@ -80,5 +81,4 @@ public final class RList extends RListBase { 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 6cb354b033a5fb8ffe88277e5cd53c4401aaffd0..4ed316e9098910dadca1a832ced61ce207fdfee0 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 @@ -27,11 +27,27 @@ 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; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; -public abstract class RListBase extends RVector implements RAbstractListVector { +/** + * Note on sharing mode for list elements: by default the sharing state of elements in a list can be + * inconsistent, e.g. a list referenced by one local variable may contain temporary vectors, or list + * references by more variables (shared list) may contain non-shared elements. The sharing state of + * the elements should be made consistent on reading from the list by the callers! When we read from + * shared list, we make the element shared. When we read from non-shared list, we make the element + * at least non-shared. There is no possible way, how a list can contain a non-shared element not + * owned by it, given that any element of some other list must be first read into variable (the + * extraction from list makes it at least non-shared, then the write makes it shared) and only then + * it can be put inside another list. This is however not true for internal code, which may read + * data from a list and then put it into another list, in such case it is responsibility of the code + * to increment the refcount of such data. Consult also the documentation of + * {@code ExtractListElement}, which is a node that can extract an element of a list or abstract + * vector and put it in the consistent sharing state. + */ +public abstract class RListBase extends RVector<Object[]> implements RAbstractListBaseVector { protected final Object[] data; @@ -51,6 +67,11 @@ public abstract class RListBase extends RVector implements RAbstractListVector { return data; } + /** + * 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 + * documentation of {@code ExtractListElement}. + */ @Override public Object getDataAtAsObject(Object store, int index) { assert store == data; @@ -78,10 +99,12 @@ public abstract class RListBase extends RVector implements RAbstractListVector { * Intended for external calls where a copy is not needed. WARNING: think carefully before using * this method rather than {@link #getDataCopy()}. */ + @Override public final Object[] getDataWithoutCopying() { return data; } + @Override public final Object[] getDataCopy() { Object[] copy = new Object[data.length]; System.arraycopy(data, 0, copy, 0, data.length); @@ -89,38 +112,17 @@ public abstract class RListBase extends RVector implements RAbstractListVector { } /** - * Return vector data (copying if necessary) that's guaranteed not to be shared with any other - * vector instance (but maybe non-temporary in terms of vector's sharing mode). - * - * @return vector data + * 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 + * documentation of {@code ExtractListElement}. */ - public final Object[] getDataNonShared() { - return isShared() ? getDataCopy() : getDataWithoutCopying(); - - } - - /** - * Return vector data (copying if necessary) that's guaranteed to be "fresh" (temporary in terms - * of vector sharing mode). - * - * @return vector data - */ - public final Object[] getDataTemp() { - return isTemporary() ? getDataWithoutCopying() : getDataCopy(); - } - @Override public final Object getDataAt(int i) { return data[i]; } - @Override - protected final String getDataAtAsString(int index) { - return RRuntime.toString(getDataAt(index)); - } - public final RListBase updateDataAt(int i, Object right, @SuppressWarnings("unused") NACheck rightNACheck) { - assert !this.isShared(); + assert !this.isShared() : "data in shared list must not be updated, make a copy"; data[i] = right; return this; } @@ -160,6 +162,11 @@ public abstract class RListBase extends RVector implements RAbstractListVector { } } + /** + * 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 + * documentation of {@code ExtractListElement}. + */ @Override public final Object getDataAtAsObject(int index) { return this.getDataAt(index); 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 05d0e6d1b1d642a39fc13b620d15a3727a3c130d..44e432804a569f815eeb52fe6b9533d3f79c97a4 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 @@ -94,7 +94,7 @@ public final class RLogical extends RScalarVector implements RAbstractLogicalVec @Override public RLogicalVector materialize() { RLogicalVector result = RDataFactory.createLogicalVectorFromScalar(value); - MemoryTracer.reportCopying(this, result); + MemoryCopyTracer.reportCopying(this, result); return result; } 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 a492093eb77cf75441f3b9218fb7b370fb9fe891..f35b7730df0d7c173f5d7e682d4576b6213135bf 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 @@ -33,7 +33,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 final class RLogicalVector extends RVector implements RAbstractLogicalVector { +public final class RLogicalVector extends RVector<byte[]> implements RAbstractLogicalVector { public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Logical.getClazz()); @@ -131,11 +131,6 @@ public final class RLogicalVector extends RVector implements RAbstractLogicalVec return data[i]; } - @Override - protected String getDataAtAsString(int index) { - return RRuntime.logicalToString(this.getDataAt(index)); - } - private RLogicalVector updateDataAt(int index, byte right, NACheck valueNACheck) { assert !this.isShared(); data[index] = right; @@ -185,6 +180,7 @@ public final class RLogicalVector extends RVector implements RAbstractLogicalVec data[toIndex] = other.getDataAt(fromIndex); } + @Override public byte[] getDataCopy() { return Arrays.copyOf(data, data.length); } @@ -193,31 +189,11 @@ public final class RLogicalVector extends RVector implements RAbstractLogicalVec * Intended for external calls where a copy is not needed. WARNING: think carefully before using * this method rather than {@link #getDataCopy()}. */ + @Override public byte[] getDataWithoutCopying() { return data; } - /** - * Return vector data (copying if necessary) that's guaranteed not to be shared with any other - * vector instance (but maybe non-temporary in terms of vector's sharing mode). - * - * @return vector data - */ - public byte[] getDataNonShared() { - return isShared() ? getDataCopy() : getDataWithoutCopying(); - - } - - /** - * Return vector data (copying if necessary) that's guaranteed to be "fresh" (temporary in terms - * of vector sharing mode). - * - * @return vector data - */ - public byte[] getDataTemp() { - return isTemporary() ? getDataWithoutCopying() : getDataCopy(); - } - @Override public RLogicalVector copyWithNewDimensions(int[] newDimensions) { return RDataFactory.createLogicalVector(data, isComplete(), newDimensions); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RObjectSize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RObjectSize.java new file mode 100644 index 0000000000000000000000000000000000000000..14b70ab39912d6a656926780f59ffe37d48e3daa --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RObjectSize.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2016, 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; + +import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; +import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; + +/** + * Support for the sizing of the objects that flow through the interpreter, i.e., mostly + * {@link RTypedValue}, but also including scalar types like {@code String} and dimension data for + * arrays, i.e., {@code int[]}. + * + * The actually implementation is controlled by {@link ObjectSizeFactory} to finesse problems with + * Java VMs that do not support reflection. + * + * Owing to the (implementation) complexity of some of the types, two levels of customization are + * provided: + * <ol> + * <li>A completely custom sizing implementation can be provided for a specific type. This effects + * all sizing computations.</li> + * <li>In any given call to {@link #getObjectSize} an instance of {@IgnoreObjectHandler} can passed. + * This allows some additional dynamic control over certain fields depending of the context of the + * call. For example, when tracking the incremental memory allocation via {@link RDataFactory}, we + * do not want to (double) count fields of type {@link RTypedValue}. However, when computing the + * total size of the object, e.g. for the {@code utils::object.size} builtin, we do want to count + * them.</li> + * </ol> + * + */ +public class RObjectSize { + public static final int INT_SIZE = 32; + public static final int DOUBLE_SIZE = 64; + public static final int BYTE_SIZE = 8; + + public interface TypeCustomizer { + /** + * Allows complete control over sizing of a type registered with + * {@link #registerTypeCustomizer}. + */ + long getObjectSize(Object obj); + } + + public interface IgnoreObjectHandler { + /** + * Controls which fields of an object passed to {@link #getObjectSize} will be ignored. + * {@code rootObject} is the initiating object and {@code obj} is some field of that object + * or one of its components. The return value should be {@code true} if {@code obj} should + * be ignored. + */ + boolean ignore(Object rootObject, Object obj); + } + + /** + * Returns an estimate of the size of the this object, including the size of any object-valued + * fields, recursively. Evidently this is a snapshot and the size can change as, e.g., + * attributes are added/removed. + * + * If called immediately after creation by {@link RDataFactory}, with an + * {@link IgnoreObjectHandler} that ignores objects created separately and, it provides an + * approximation of the incremental memory usage of the system. + * + * @param ignoreObjectHandler An object that is called to decide whether to include the + * contribution a field of this object (and its sub-objects) in the result. Passing + * {@code null} includes everything. N.B. {@code obj} is typed as {@code Object} only + * to allow scalar typed such as {@code String} to be passed. + * + */ + public static long getObjectSize(Object obj, IgnoreObjectHandler ignoreObjectHandler) { + return (int) ObjectSizeFactory.getInstance().getObjectSize(obj, ignoreObjectHandler); + } + + /** + * Register a {@link TypeCustomizer} for {@code klass} and its subclasses. I.e. and object + * {@code obj} is customized iff {@code klass.isAssignableFrom(obj.getClass())}. + */ + public static void registerTypeCustomizer(Class<?> klass, TypeCustomizer typeCustomizer) { + ObjectSizeFactory.getInstance().registerTypeCustomizer(klass, typeCustomizer); + } + + /** + * This denotes a special customizer that completely ignores instances of the type and its + * subclasses. It allows a more efficient implementation as the type can be suppressed + * completely from the computation at the time fields of a containing type are analyzed. + */ + public static final TypeCustomizer IGNORE = new TypeCustomizer() { + + @Override + public long getObjectSize(Object obj) { + return 0; + } + + }; + + // TODO construct proper customizers for some of these. + static { + registerTypeCustomizer(Frame.class, IGNORE); + registerTypeCustomizer(FrameDescriptor.class, IGNORE); + registerTypeCustomizer(Node.class, IGNORE); + registerTypeCustomizer(CallTarget.class, IGNORE); + registerTypeCustomizer(RBuiltinDescriptor.class, IGNORE); + registerTypeCustomizer(RPromise.Closure.class, IGNORE); + registerTypeCustomizer(Assumption.class, IGNORE); + registerTypeCustomizer(RCaller.class, IGNORE); + registerTypeCustomizer(SEXPTYPE.class, IGNORE); + } + +} 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 7a1944f3ea0fffa3b0f70da0dc5bc55795507a71..922551aa37e41c057c5c521fb61e722cce7d9db3 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 @@ -29,6 +29,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; 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.Utils; import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -273,6 +274,12 @@ public class RPairList extends RSharingAttributeStorage implements RAbstractCont result = (RPairList) result.cdr; original = origList.cdr; } + if (getAttributes() != null) { + RAttributes newAttributes = result.initAttributes(); + for (RAttribute attr : getAttributes()) { + newAttributes.put(attr.getName(), attr.getValue()); + } + } return result; } @@ -311,7 +318,7 @@ public class RPairList extends RSharingAttributeStorage implements RAbstractCont boolean complete = RDataFactory.COMPLETE_VECTOR; int i = 0; while (true) { - data[i] = pl.tag.toString(); + data[i] = Utils.toString(pl.tag); if (pl.tag == RRuntime.STRING_NA) { complete = false; } 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 d843cacfb937a8518c91151e91e7e33b3c553076..a18f274d43736e0c7e9936de1eaa8d6adf0aa544 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 @@ -65,7 +65,7 @@ public final class RRaw extends RScalarVector implements RAbstractRawVector { @Override public RRawVector materialize() { RRawVector result = RDataFactory.createRawVector(new byte[]{value}); - MemoryTracer.reportCopying(this, result); + MemoryCopyTracer.reportCopying(this, result); return result; } 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 01ef62b132ffb705df18b6646b7ca419a06e3da9..6fdbf806bf2d4e258c6eeb0d133dd3dc0ae0be9c 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 @@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; -public final class RRawVector extends RVector implements RAbstractRawVector { +public final class RRawVector extends RVector<byte[]> implements RAbstractRawVector { public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Raw.getClazz()); @@ -114,51 +114,25 @@ public final class RRawVector extends RVector implements RAbstractRawVector { return RDataFactory.createRaw(data[i]); } + @Override public byte[] getDataCopy() { - byte[] copy = new byte[data.length]; - System.arraycopy(data, 0, copy, 0, data.length); - return copy; + return Arrays.copyOf(data, data.length); } /** * Intended for external calls where a copy is not needed. WARNING: think carefully before using * this method rather than {@link #getDataCopy()}. */ + @Override public byte[] getDataWithoutCopying() { return data; } - /** - * Return vector data (copying if necessary) that's guaranteed not to be shared with any other - * vector instance (but maybe non-temporary in terms of vector's sharing mode). - * - * @return vector data - */ - public byte[] getDataNonShared() { - return isShared() ? getDataCopy() : getDataWithoutCopying(); - - } - - /** - * Return vector data (copying if necessary) that's guaranteed to be "fresh" (temporary in terms - * of vector sharing mode). - * - * @return vector data - */ - public byte[] getDataTemp() { - return isTemporary() ? getDataWithoutCopying() : getDataCopy(); - } - @Override public RRawVector copyWithNewDimensions(int[] newDimensions) { return RDataFactory.createRawVector(data, newDimensions); } - @Override - protected String getDataAtAsString(int index) { - return getDataAt(index).toString(); - } - @Override public RRawVector materialize() { return this; 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 6e4a7ca5d9590b16c937b8bb62608c6f25ef8cd7..5019f8fe5220211227b7ca98b675088b54b1804b 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 @@ -141,35 +141,35 @@ public abstract class RScalarVector extends RScalar implements RAbstractVector { } @Override - public RVector copyResized(int size, boolean fillNA) { - RVector result = materialize().copyResized(size, fillNA); - MemoryTracer.reportCopying(this, result); + public RVector<?> copyResized(int size, boolean fillNA) { + RVector<?> result = materialize().copyResized(size, fillNA); + MemoryCopyTracer.reportCopying(this, result); return result; } @Override public RAbstractVector copyWithNewDimensions(int[] newDimensions) { RAbstractVector result = materialize().copyWithNewDimensions(newDimensions); - MemoryTracer.reportCopying(this, result); + MemoryCopyTracer.reportCopying(this, result); return result; } @Override - public RVector copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { - RVector result = materialize().copyResizedWithDimensions(newDimensions, fillNA); - MemoryTracer.reportCopying(this, result); + public RVector<?> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { + RVector<?> result = materialize().copyResizedWithDimensions(newDimensions, fillNA); + MemoryCopyTracer.reportCopying(this, result); return result; } @Override public RAbstractVector copyDropAttributes() { - RVector result = materialize().copyDropAttributes(); - MemoryTracer.reportCopying(this, result); + RVector<?> result = materialize().copyDropAttributes(); + MemoryCopyTracer.reportCopying(this, result); return result; } @Override - public RVector createEmptySameType(int newLength, boolean newIsComplete) { + public RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { return materialize().createEmptySameType(newLength, newIsComplete); } 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 3dcc48a783d72896755c68f58238721596a0d86c..d60927efc5a4df2f52b7c07f7e76cea6883903cc 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 @@ -79,13 +79,13 @@ public abstract class RSequence implements RAbstractVector { throw RInternalError.shouldNotReachHere(); } - public final RVector createVector() { - RVector result = internalCreateVector(); - MemoryTracer.reportCopying(this, result); + public final RVector<?> createVector() { + RVector<?> result = internalCreateVector(); + MemoryCopyTracer.reportCopying(this, result); return result; } - protected abstract RVector internalCreateVector(); + protected abstract RVector<?> internalCreateVector(); @Override public final RAbstractVector copy() { @@ -181,10 +181,10 @@ public abstract class RSequence implements RAbstractVector { } @Override - public final RVector copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { + 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); + RVector<?> result = copyResized(newDimensions[0] * newDimensions[1], fillNA); result.setDimensions(newDimensions); return result; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RShareable.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RShareable.java index 6229258c14696ab8c4700863905a45afe7e74e0e..5729a5ce08aa8fee7c09aa62981f168acadd1049 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RShareable.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RShareable.java @@ -40,8 +40,14 @@ public interface RShareable extends RTypedValue { return copy(); } + /** + * It is invalid to invoke this method on 'shared permanent' shareables. + */ void incRefCount(); + /** + * It is invalid to invoke this method on 'temporary' shareables. + */ void decRefCount(); boolean isSharedPermanent(); 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 e049da26b83fe32ab201e91a24f546a14502391b..a685b13e48aaaef62c457462dbf5731b96aa370a 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 @@ -41,28 +41,30 @@ public abstract class RSharingAttributeStorage extends RAttributeStorage impleme @Override public final void incRefCount() { + assert refCount != SHARED_PERMANENT_VAL : "cannot incRefCount of shared permanent value"; refCount++; } @Override public final void decRefCount() { - assert refCount > 0; + assert refCount != SHARED_PERMANENT_VAL : "cannot decRefCount of shared permanent value"; + assert refCount > 0 : "cannot decRefCount when refCount <= 0"; refCount--; } @Override - public boolean isSharedPermanent() { + public final boolean isSharedPermanent() { return refCount == SHARED_PERMANENT_VAL; } @Override - public RSharingAttributeStorage makeSharedPermanent() { + public final RSharingAttributeStorage makeSharedPermanent() { refCount = SHARED_PERMANENT_VAL; return this; } @Override - public RTypedValue getNonShared() { + public final RTypedValue getNonShared() { if (isShared()) { RShareable res = copy(); assert res.isTemporary(); 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 764f4c4b4ba2c88556989eb83461fdf4b8409bc5..af3281e0c19f749edcdbd5f3ab44ed4562315ce6 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 @@ -74,7 +74,7 @@ public final class RString extends RScalarVector implements RAbstractStringVecto @Override public RStringVector materialize() { RStringVector result = RDataFactory.createStringVector(new String[]{getValue()}, isComplete()); - MemoryTracer.reportCopying(this, result); + MemoryCopyTracer.reportCopying(this, result); return result; } 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 53f6667432c8ca54341247372fbab98b5a38f82f..b4110bd81af1e69378fa0eff2b77030a7ef682ff 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 @@ -34,7 +34,7 @@ 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; -public final class RStringVector extends RVector implements RAbstractStringVector { +public final class RStringVector extends RVector<String[]> implements RAbstractStringVector { public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Character.getClazz()); @@ -89,6 +89,7 @@ public final class RStringVector extends RVector implements RAbstractStringVecto return data.length; } + @Override public String[] getDataCopy() { String[] copy = new String[data.length]; System.arraycopy(data, 0, copy, 0, data.length); @@ -99,31 +100,11 @@ public final class RStringVector extends RVector implements RAbstractStringVecto * Intended for external calls where a copy is not needed. WARNING: think carefully before using * this method rather than {@link #getDataCopy()}. */ + @Override public String[] getDataWithoutCopying() { return data; } - /** - * Return vector data (copying if necessary) that's guaranteed not to be shared with any other - * vector instance (but maybe non-temporary in terms of vector's sharing mode). - * - * @return vector data - */ - public String[] getDataNonShared() { - return isShared() ? getDataCopy() : getDataWithoutCopying(); - - } - - /** - * Return vector data (copying if necessary) that's guaranteed to be "fresh" (temporary in terms - * of vector sharing mode). - * - * @return vector data - */ - public String[] getDataTemp() { - return isTemporary() ? getDataWithoutCopying() : getDataCopy(); - } - @Override public String toString() { return toString(i -> getDataAt(i)); @@ -146,11 +127,6 @@ public final class RStringVector extends RVector implements RAbstractStringVecto return data[i]; } - @Override - protected String getDataAtAsString(int index) { - return getDataAt(index); - } - public RStringVector updateDataAt(int i, String right, NACheck rightNACheck) { if (this.isShared()) { throw RInternalError.shouldNotReachHere("update shared 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 159addc3e228b3bda6e2e3bbcc9e9504544c5987..2768eba5bde538d2410ea087faf6eed0ee447056 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 @@ -26,12 +26,9 @@ import java.util.function.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.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RPerfStats; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.SuppressFBWarnings; @@ -57,7 +54,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; * - non-shared => shared * </pre> */ -public abstract class RVector extends RSharingAttributeStorage implements RShareable, RAbstractVector, RFFIAccess { +public abstract class RVector<ArrayT> extends RSharingAttributeStorage implements RAbstractVector, RFFIAccess { private static final RStringVector implicitClassHeaderArray = RDataFactory.createStringVector(new String[]{RType.Array.getName()}, true); private static final RStringVector implicitClassHeaderMatrix = RDataFactory.createStringVector(new String[]{RType.Matrix.getName()}, true); @@ -98,6 +95,37 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare } } + /** + * Intended for external calls where a mutable copy is needed. + */ + public abstract ArrayT getDataCopy(); + + /** + * Intended for external calls where a copy is not needed. WARNING: think carefully before using + * this method rather than {@link #getDataCopy()}. + */ + public abstract ArrayT getDataWithoutCopying(); + + /** + * Return vector data (copying if necessary) that's guaranteed not to be shared with any other + * vector instance (but maybe non-temporary in terms of vector's sharing mode). + * + * @return vector data + */ + public final ArrayT getDataNonShared() { + return isShared() ? getDataCopy() : getDataWithoutCopying(); + } + + /** + * Return vector data (copying if necessary) that's guaranteed to be "fresh" (temporary in terms + * of vector sharing mode). + * + * @return vector data + */ + public final ArrayT getDataTemp() { + return isTemporary() ? getDataWithoutCopying() : getDataCopy(); + } + public final int[] getInternalDimensions() { return dimensions; } @@ -502,11 +530,11 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare return setClassAttrInternal(this, classAttr); } - public static RAbstractContainer setVectorClassAttr(RVector vector, RStringVector classAttr) { + public static RAbstractContainer setVectorClassAttr(RVector<?> vector, RStringVector classAttr) { return setClassAttrInternal(vector, classAttr); } - private static RAbstractContainer setClassAttrInternal(RVector vector, RStringVector classAttr) { + private static RAbstractContainer setClassAttrInternal(RVector<?> vector, RStringVector classAttr) { if (vector.attributes == null && classAttr != null && classAttr.getLength() != 0) { vector.initAttributes(); } @@ -537,7 +565,7 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare return vector; } - public final void setAttributes(RVector result) { + public final void setAttributes(RVector<?> result) { result.names = this.names; result.dimNames = this.dimNames; result.rowNames = this.rowNames; @@ -550,70 +578,68 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare // public interface *copy* methods are final and delegate to *internalCopyAndReport* methods @Override - public final RVector copy() { - RVector result = internalCopyAndReport(); + public final RVector<ArrayT> copy() { + RVector<ArrayT> result = internalCopyAndReport(); setAttributes(result); - incCopyCount(); result.setTypedValueInfo(getTypedValueInfo()); return result; } @Override - public final RVector copyDropAttributes() { - RVector result = internalCopyAndReport(); - return result; + public final RVector<ArrayT> copyDropAttributes() { + return internalCopyAndReport(); } @Override - public final RVector deepCopy() { - RVector result = internalDeepCopyAndReport(); + public final RVector<ArrayT> deepCopy() { + RVector<ArrayT> result = internalDeepCopyAndReport(); setAttributes(result); return result; } @Override - public final RVector copyResized(int size, boolean fillNA) { + public final RVector<ArrayT> copyResized(int size, boolean fillNA) { return internalCopyResizedAndReport(size, fillNA); } // *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 internalCopyAndReport() { - RVector result = internalCopy(); - MemoryTracer.reportCopying(this, result); + protected final RVector<ArrayT> internalCopyAndReport() { + RVector<ArrayT> result = internalCopy(); + MemoryCopyTracer.reportCopying(this, result); return result; } - protected final RVector internalDeepCopyAndReport() { - RVector result = internalDeepCopy(); - MemoryTracer.reportCopying(this, result); + protected final RVector<ArrayT> internalDeepCopyAndReport() { + RVector<ArrayT> result = internalDeepCopy(); + MemoryCopyTracer.reportCopying(this, result); return result; } - protected final RVector internalCopyResizedAndReport(int size, boolean fillNA) { - RVector result = internalCopyResized(size, fillNA); - MemoryTracer.reportCopying(this, 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 internalCopyResized(int size, boolean fillNA); + protected abstract RVector<ArrayT> internalCopyResized(int size, boolean fillNA); // to be overridden by recursive structures - protected RVector internalDeepCopy() { + protected RVector<ArrayT> internalDeepCopy() { return internalCopy(); } - protected abstract RVector internalCopy(); + protected abstract RVector<ArrayT> internalCopy(); @Override - public RVector copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { + public RVector<ArrayT> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { // TODO support for higher dimensions assert newDimensions.length == 2; - RVector result = copyResized(newDimensions[0] * newDimensions[1], fillNA); + RVector<ArrayT> result = copyResized(newDimensions[0] * newDimensions[1], fillNA); result.setDimensions(newDimensions); return result; } @@ -622,8 +648,6 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare return internalVerify(); } - protected abstract String getDataAtAsString(int index); - protected abstract boolean internalVerify(); /** @@ -635,7 +659,7 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare * @param naCheck NA check used to change vector's mode in case value is NA * @return updated vector */ - public abstract RVector updateDataAtAsObject(int i, Object o, NACheck naCheck); + public abstract RVector<ArrayT> updateDataAtAsObject(int i, Object o, NACheck naCheck); public abstract void transferElementSameType(int toIndex, RAbstractVector fromVector, int fromIndex); @@ -667,7 +691,7 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare * 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 copyAttributesFrom(RVector vector) { + protected final RAttributable copyAttributesFrom(RVector<?> vector) { if (vector.getDimensions() == null || vector.getDimensions().length != 1) { this.names = vector.getNames(); } @@ -719,7 +743,7 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare } @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "all three string constants below are supposed to be used as identities") - public final RVector copyRegAttributesFrom(RAbstractContainer vector) { + public final RVector<ArrayT> copyRegAttributesFrom(RAbstractContainer vector) { RAttributes orgAttributes = vector.getAttributes(); if (orgAttributes != null) { Object newRowNames = null; @@ -739,13 +763,13 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare } @Override - public final RVector resize(int size) { + public final RVector<ArrayT> resize(int size) { return resize(size, true); } - private RVector resize(int size, boolean resetAll) { + private RVector<ArrayT> resize(int size, boolean resetAll) { this.complete &= getLength() >= size; - RVector res = this; + RVector<ArrayT> res = this; RStringVector oldNames = res.names; res = copyResized(size, true); if (this.isShared()) { @@ -842,45 +866,6 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare } } - private static final ConditionProfile statsProfile = ConditionProfile.createBinaryProfile(); - - @CompilationFinal private static PerfHandler stats; - - private static void incCopyCount() { - if (statsProfile.profile(stats != null)) { - stats.record(null); - } - } - - static { - RPerfStats.register(new PerfHandler()); - } - - private static class PerfHandler implements RPerfStats.Handler { - - private static int count; - - void record(@SuppressWarnings("unused") Object data) { - count++; - } - - @Override - public void initialize(String optionData) { - stats = this; - count = 0; - } - - @Override - public String getName() { - return "vectorcopies"; - } - - @Override - public void report() { - RPerfStats.out().printf("NUMBER OF VECTOR COPIES: %d\n", count); - } - } - private static final int MAX_TOSTRING_LENGTH = 100; protected String toString(Function<Integer, String> element) { 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/closures/RAbstactVectorToListClosure.java index 1bd456fb5d56fe5a0b381bd36d0ac97435466f1f..4d076c044ef7f3d59ad3b6f6ffc59ef547bcac07 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/closures/RAbstactVectorToListClosure.java @@ -22,10 +22,8 @@ */ package com.oracle.truffle.r.runtime.data.closures; -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.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; @@ -66,12 +64,7 @@ final class RAbstactVectorToListClosure extends RToVectorClosure implements RAbs } @Override - public RVector createEmptySameType(int newLength, boolean newIsComplete) { + public RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { return RDataFactory.createList(new Object[newLength]); } - - @Override - public RStringVector getNames() { - throw RInternalError.shouldNotReachHere(); - } } 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 0d9694e313d36adbf84fb6ce1624337608f43055..1d75a18aa146d5ad1190a62f10bfa26af0c40fd9 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 @@ -124,7 +124,7 @@ public class RClosures { return createFactorToVector(factor, withNames, RFactor.getLevels(attrProfiles, factor)); } - public static RAbstractVector createFactorToVector(RAbstractIntVector factor, boolean withNames, RVector levels) { + public static RAbstractVector createFactorToVector(RAbstractIntVector factor, boolean withNames, RVector<?> levels) { if (levels == null) { return new RFactorToStringVectorClosure(factor, null, withNames); } else { 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 index 260c400e3bce2ba9be279445876cb6e99cf8c27b..136d4e7653c752a161f7afc5af630da51b1b6341 100644 --- 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 @@ -23,6 +23,7 @@ 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; @@ -39,6 +40,6 @@ final class RComplexToStringVectorClosure extends RToStringVectorClosure impleme if (!vector.isComplete() && RRuntime.isNA(data)) { return RRuntime.STRING_NA; } - return RRuntime.complexToString(data); + return RContext.getRRuntimeASTAccess().encodeComplex(data); } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToStringVectorClosure.java index c1de5e4bf033f20c6c5dc4bc249cb610911a6488..6a7ce849bbba683617452959e842f43d5c849f60 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToStringVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToStringVectorClosure.java @@ -23,6 +23,7 @@ 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.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @@ -38,7 +39,7 @@ final class RDoubleToStringVectorClosure extends RToStringVectorClosure implemen if (!vector.isComplete() && RRuntime.isNA(data)) { return RRuntime.STRING_NA; } else { - return RRuntime.doubleToStringNoCheck(data); + return RContext.getRRuntimeASTAccess().encodeDouble(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 a8ce9efae4859ce2a4c8ff947d12b6f319bc27c5..e469c8b0d07608030b4d8dc22e2a7f7e305dca14 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 @@ -36,7 +36,7 @@ abstract class RToComplexVectorClosure extends RToVectorClosure implements RAbst } @Override - public final RVector createEmptySameType(int newLength, boolean newIsComplete) { + public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { return RDataFactory.createComplexVector(new double[newLength << 1], newIsComplete); } 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 e944259d249657ac2748e987aff3858f2309c163..55cc0daa12f45425c6a32fe8a291a56f0b9d5b64 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 @@ -35,7 +35,7 @@ abstract class RToDoubleVectorClosure extends RToVectorClosure implements RAbstr } @Override - public final RVector createEmptySameType(int newLength, boolean newIsComplete) { + public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { return RDataFactory.createDoubleVector(new double[newLength], newIsComplete); } 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 5c8c44c7d7e9ebcb66d6f57e2a8810b00934c449..132946950c1687bf8b1a42f9b3ca342a1f4aba19 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 @@ -35,7 +35,7 @@ abstract class RToIntVectorClosure extends RToVectorClosure implements RAbstract } @Override - public final RVector createEmptySameType(int newLength, boolean newIsComplete) { + public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { return RDataFactory.createIntVector(new int[newLength], newIsComplete); } 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 d907512a2306025b524026cda648d144a469049a..38d3cbeca01fc6ce77e782bd95ef49b6aef2fbf0 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 @@ -35,7 +35,7 @@ abstract class RToStringVectorClosure extends RToVectorClosure implements RAbstr } @Override - public final RVector createEmptySameType(int newLength, boolean newIsComplete) { + public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { return RDataFactory.createStringVector(new String[newLength], newIsComplete); } 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 0fe0baccfc90e7e0bb0b1a374322b1d431b37cc2..8c385a8fcc75d1697bd33b8e414738b79957d6fd 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 @@ -22,7 +22,7 @@ */ package com.oracle.truffle.r.runtime.data.closures; -import com.oracle.truffle.r.runtime.data.MemoryTracer; +import com.oracle.truffle.r.runtime.data.MemoryCopyTracer; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RAttributes; import com.oracle.truffle.r.runtime.data.RList; @@ -129,22 +129,22 @@ abstract class RToVectorClosure implements RAbstractVector { @Override public final RAbstractVector copy() { RAbstractVector result = vector.copy(); - MemoryTracer.reportCopying(this, result); + MemoryCopyTracer.reportCopying(this, result); return result; } @Override - public final RVector copyResized(int size, boolean fillNA) { - RVector result = vector.copyResized(size, fillNA); - MemoryTracer.reportCopying(this, result); + public final RVector<?> copyResized(int size, boolean fillNA) { + RVector<?> result = vector.copyResized(size, fillNA); + MemoryCopyTracer.reportCopying(this, result); return result; } @Override - public final RVector copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { + 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); + RVector<?> result = copyResized(newDimensions[0] * newDimensions[1], fillNA); result.setDimensions(newDimensions); return result; } @@ -152,7 +152,7 @@ abstract class RToVectorClosure implements RAbstractVector { @Override public final RAbstractVector copyDropAttributes() { RAbstractVector result = vector.copyDropAttributes(); - MemoryTracer.reportCopying(this, result); + MemoryCopyTracer.reportCopying(this, result); return result; } 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 befd4e867877b9b1375e1184dec6ca9686960c2e..2125cce5eeacdf0581e006a53de42b1ac2046631 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 @@ -51,6 +51,11 @@ public interface RAbstractContainer extends RAttributable, RTypedValue { Object getDataAtAsObject(int index); + /** + * 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 + * documentation of {@code ExtractListElement}. + */ default Object getDataAtAsObject(@SuppressWarnings("unused") Object store, int index) { return getDataAtAsObject(index); } 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 new file mode 100644 index 0000000000000000000000000000000000000000..0bf27c70357a457355e86c2d563c8cb40414fd08 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListBaseVector.java @@ -0,0 +1,58 @@ +/* + * 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.model; + +import com.oracle.truffle.r.runtime.data.RNull; + +public interface RAbstractListBaseVector extends RAbstractVector { + + @Override + Object getDataAtAsObject(int index); + + @Override + default Object getDataAtAsObject(Object store, int i) { + return getDataAtAsObject(i); + } + + 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 void setNA(Object store, int index) { + setDataAt(store, index, RNull.instance); + } +} 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 8a4905a799dc4a288c6d8373558c6a16e26d9120..681861e7e5429f2649ad951488a43344072548ef 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 @@ -24,28 +24,8 @@ package com.oracle.truffle.r.runtime.data.model; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RStringVector; -public interface RAbstractListVector extends RAbstractVector { - - @Override - Object getDataAtAsObject(int index); - - @Override - default Object getDataAtAsObject(Object store, int i) { - return getDataAtAsObject(i); - } - - Object getDataAt(int index); - - @Override - RList materialize(); - - @Override - default boolean checkCompleteness() { - return true; - } +public interface RAbstractListVector extends RAbstractListBaseVector { @Override default RType getRType() { @@ -53,19 +33,5 @@ public interface RAbstractListVector extends RAbstractVector { } @Override - default Class<?> getElementClass() { - return Object.class; - } - - @SuppressWarnings("unused") - default void setDataAt(Object store, int index, Object value) { - throw new UnsupportedOperationException(); - } - - RStringVector getNames(); - - @Override - default void setNA(Object store, int index) { - setDataAt(store, index, RNull.instance); - } + RList materialize(); } 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 a2ae57288b474717f66033b2bacd43a882e5e899..a6e9a39c047cdb9a796219423e685ed5345f5f8e 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 @@ -24,11 +24,11 @@ package com.oracle.truffle.r.runtime.data.model; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.MemoryTracer; +import com.oracle.truffle.r.runtime.data.MemoryCopyTracer; import com.oracle.truffle.r.runtime.data.RVector; /** - * When implementing, make sure to invoke related {@link MemoryTracer} methods. + * When implementing, make sure to invoke related {@link MemoryCopyTracer} methods. */ public interface RAbstractVector extends RAbstractContainer { @@ -43,17 +43,17 @@ public interface RAbstractVector extends RAbstractContainer { return copy(); } - RVector copyResized(int size, boolean fillNA); + RVector<?> copyResized(int size, boolean fillNA); RAbstractVector copyWithNewDimensions(int[] newDimensions); - RVector copyResizedWithDimensions(int[] newDimensions, boolean fillNA); + RVector<?> copyResizedWithDimensions(int[] newDimensions, boolean fillNA); RAbstractVector copyDropAttributes(); - RVector createEmptySameType(int newLength, boolean newIsComplete); + RVector<?> createEmptySameType(int newLength, boolean newIsComplete); - RVector materialize(); + 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 e66aef15b5c364f8e2fc610525b1286ef902d4f1..f8f7aad81987779a9cfa1dd2d42043a38e11d070 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 @@ -100,7 +100,7 @@ import com.oracle.truffle.r.runtime.env.frame.REnvTruffleFrameAccess; * <p> * The logic for implementing the three different forms of * {@link com.oracle.truffle.r.runtime.context.RContext.ContextKind} is encapsulated in the - * {@link #createContext} method. + * {@link #setupContext} method. */ public abstract class REnvironment extends RAttributeStorage { @@ -111,22 +111,25 @@ public abstract class REnvironment extends RAttributeStorage { return implicitClass; } - public static class ContextStateImpl implements RContext.ContextState { + public static final class ContextStateImpl implements RContext.ContextState { private SearchPath searchPath; private final MaterializedFrame globalFrame; private Base baseEnv; private REnvironment namespaceRegistry; private MaterializedFrame parentGlobalFrame; // SHARED_PARENT_RW only - ContextStateImpl(MaterializedFrame globalFrame, SearchPath searchPath) { + private ContextStateImpl(MaterializedFrame globalFrame) { this.globalFrame = globalFrame; - this.searchPath = searchPath; } - ContextStateImpl(MaterializedFrame globalFrame, SearchPath searchPath, Base baseEnv, REnvironment namespaceRegistry) { - this(globalFrame, searchPath); - this.baseEnv = baseEnv; - this.namespaceRegistry = namespaceRegistry; + private void initialize(SearchPath searchPathA) { + this.searchPath = searchPathA; + } + + private void initialize(SearchPath searchPathA, Base baseEnvA, REnvironment namespaceRegistryA) { + this.searchPath = searchPathA; + this.baseEnv = baseEnvA; + this.namespaceRegistry = namespaceRegistryA; } public REnvironment getGlobalEnv() { @@ -165,13 +168,20 @@ public abstract class REnvironment extends RAttributeStorage { this.namespaceRegistry = namespaceRegistry; } + @Override + public RContext.ContextState initialize(RContext context) { + setupContext(this, context, globalFrame); + return this; + + } + @Override public void beforeDestroy(RContext context) { beforeDestroyContext(context, this); } - public static ContextStateImpl newContext(RContext context) { - return createContext(context, RRuntime.createNonFunctionFrame("global")); + public static ContextStateImpl newContextState() { + return new ContextStateImpl(RRuntime.createNonFunctionFrame("global")); } } @@ -311,7 +321,7 @@ public abstract class REnvironment extends RAttributeStorage { * N.B. {@link RContext#stateREnvironment} accesses the new, as yet uninitialized * {@link ContextStateImpl} object */ - private static ContextStateImpl createContext(RContext context, MaterializedFrame globalFrame) { + private static void setupContext(ContextStateImpl contextState, RContext context, MaterializedFrame globalFrame) { switch (context.getKind()) { case SHARE_PARENT_RW: { /* @@ -331,9 +341,9 @@ public abstract class REnvironment extends RAttributeStorage { SearchPath searchPath = initSearchList(prevGlobalEnv); searchPath.updateGlobal(newGlobalEnv); parentState.getBaseEnv().safePut(".GlobalEnv", newGlobalEnv); - ContextStateImpl result = new ContextStateImpl(globalFrame, searchPath, parentBaseEnv, parentState.getNamespaceRegistry()); - result.parentGlobalFrame = prevGlobalFrame; - return result; + contextState.initialize(searchPath, parentBaseEnv, parentState.getNamespaceRegistry()); + contextState.parentGlobalFrame = prevGlobalFrame; + break; } case SHARE_PARENT_RO: { @@ -359,12 +369,14 @@ public abstract class REnvironment extends RAttributeStorage { newNamespaceRegistry.safePut("base", newBaseEnv.namespaceEnv); newBaseEnv.safePut(".GlobalEnv", newGlobalEnv); SearchPath newSearchPath = initSearchList(newGlobalEnv); - return new ContextStateImpl(globalFrame, newSearchPath, newBaseEnv, newNamespaceRegistry); + contextState.initialize(newSearchPath, newBaseEnv, newNamespaceRegistry); + break; } case SHARE_NOTHING: { // SHARE_NOTHING: baseInitialize takes care of everything - return new ContextStateImpl(globalFrame, new SearchPath()); + contextState.initialize(new SearchPath()); + break; } default: @@ -594,7 +606,7 @@ public abstract class REnvironment extends RAttributeStorage { detachException(RError.Message.ENV_DETACH_BASE); } if (pos <= 0 || pos >= searchPath.size()) { - detachException(RError.Message.INVALID_POS_ARGUMENT); + detachException(RError.Message.INVALID_ARGUMENT, "pos"); } assert pos != 1; // explicitly checked in caller // N.B. pos is 1-based @@ -608,8 +620,8 @@ public abstract class REnvironment extends RAttributeStorage { } @TruffleBoundary - private static void detachException(RError.Message message) throws DetachException { - throw new DetachException(message); + private static void detachException(RError.Message message, Object... args) throws DetachException { + throw new DetachException(message, args); } /** 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 962d3f86c196a1270c1dea1ccf676cf3a6ff6fc3..da58110d0b4a622e7d3f3bbae954b875d1e08e81 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 @@ -135,6 +135,7 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess { } @Override + @TruffleBoundary public RStringVector ls(boolean allNames, Pattern pattern, boolean sorted) { FrameDescriptor fd = frame.getFrameDescriptor(); String[] names = getStringIdentifiers(fd); @@ -157,6 +158,7 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess { } @Override + @TruffleBoundary public boolean bindingIsLocked(String key) { return lockedBindings != null && lockedBindings.contains(key); } @@ -181,13 +183,14 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess { } @Override + @TruffleBoundary public void unlockBinding(String key) { if (lockedBindings != null) { lockedBindings.remove(key); } } - private static String[] getStringIdentifiers(FrameDescriptor fd) { + public static String[] getStringIdentifiers(FrameDescriptor fd) { return fd.getIdentifiers().stream().filter(e -> (e instanceof String)).toArray(String[]::new); } } 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 af64e0c2b744533d75fc7e44b8116cb713bb40e5..81e2536a03764a896477ce6218dd8856acaaa115 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, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,6 +22,34 @@ */ package com.oracle.truffle.r.runtime.env.frame; +import java.util.ArrayList; + +import com.oracle.truffle.r.runtime.RCaller; +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 { - OnExit; + /** + * 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, + /** + * This frame slot is used to track result visibility. It can contain one of three values: + * <ul> + * <li>{@link Boolean#TRUE} if the result is currently visible</li> + * <li>{@link Boolean#FALSE} if the result is currently not visible</li> + * <li>{@code null} if the visibility was not set yet</li> + * </ul> + * + * Whenever an {@RBuiltinNode} is called via {@code RCallNode}, the resulting visibility is + * stored in the current frame. At the end of a {@code FunctionDefinitionNode}, the current + * state is stored into {@link RCaller#setVisibility(boolean)} if it is non-{@code null}. After + * each call site, the value of {@link RCaller#getVisibility()} is extracted and stored into the + * frame slot. + */ + Visibility; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java index 8770a46110928aa432433cce70c077fa435e68df..76c8f10cd072e5f36abdb14b96dbb7566140a538 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java @@ -43,8 +43,9 @@ public interface CallRFFI { void invokeVoidCall(long address, String name, Object[] args); /** - * This interface is initialized very early, before the {@code tempDir} is established. This - * call sets the value. + * This interface is instantiated very early and sets the FFI global variables as part of that + * process. However, at that stage {@code tempDir} is not established so this call exists to set + * the value later. */ void setTempDir(String tempDir); @@ -52,4 +53,5 @@ public interface CallRFFI { * Sets the {@code R_Interactive} FFI variable. Similar rationale to {#link setTmpDir}. */ void setInteractive(boolean interactive); + } 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 new file mode 100644 index 0000000000000000000000000000000000000000..28ad96a3b65095f9363cfab470a76e9078a8a576 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016, 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.ffi; + +/** + * Miscellaneous methods implemented in native code. + * + */ +public interface MiscRFFI { + double exactSum(double[] values, boolean hasNa, boolean naRm); + +} 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 841567fef07f38e99e8b1554a47de817c8e0028b..a88e98267e13b5ad8847235b47cb76fc1fbdf153 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 @@ -40,6 +40,7 @@ package com.oracle.truffle.r.runtime.ffi; * <li>{@link PCRERFFI}: interface to PCRE library (Perl regexp).</li> * <li>{@link ZipRFFI}: interface to zip compression</li> * <li>{@link REmbedRFFI}: interface to embedded support</li> + * <li>{@link MiscRFFI}: interface to miscellaneous native functions</li> * </ul> * * These interfaces may be implemented by one or more providers, specified either when the FastR @@ -70,4 +71,6 @@ public interface RFFI { REmbedRFFI getREmbedRFFI(); + MiscRFFI getMiscRFFI(); + } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIContextStateFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIContextStateFactory.java index f18abc1221f6e63e44c8e67e04ee2f18e95cfd49..934ad58e5ef650278cab6880dc4afc692cf5c19a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIContextStateFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIContextStateFactory.java @@ -37,7 +37,7 @@ public class RFFIContextStateFactory { theFactory = factory; } - public static ContextState newContext(RContext context) { - return theFactory.newContext(context); + public static ContextState newContextState() { + return theFactory.newContextState(); } } 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 cdbe8d0b82ad6d03f6e2848499ccc4550be3d3d0..fa9895000472ac2ffc16396c3cd140d257e334d7 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,7 +23,6 @@ package com.oracle.truffle.r.runtime.ffi; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.context.RContext.ContextState; @@ -32,7 +31,7 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextState; * choice of factory is made by the R engine and set here by the call to {@link #setRFFIFactory}. * * The RFFI may need to do special things in the case of multiple contexts, hence any given factory - * must support the {@link #newContext(RContext)} method. However, since we don't know exactly which + * must support the {@link #newContextState()} method. However, since we don't know exactly which * factory will be used, {@link RContext} references the {@link RFFIContextStateFactory} class. */ public abstract class RFFIFactory { @@ -66,49 +65,5 @@ public abstract class RFFIFactory { */ protected abstract RFFI createRFFI(); - public LapackRFFI getLapackRFFI() { - throw missing("Lapack"); - } - - public StatsRFFI getStatsRFFI() { - throw missing("Stats"); - } - - public ToolsRFFI getToolsRFFI() { - throw missing("Tools"); - } - - public GridRFFI getGridRFFI() { - throw missing("Grid"); - } - - public RApplRFFI getRApplRFFI() { - throw missing("RDerived"); - } - - public CRFFI getCRFFI() { - throw missing("C"); - } - - public CallRFFI getCallRFFI() { - throw missing("Call"); - } - - public UserRngRFFI getUserRngRFFI() { - throw missing("UserRNG"); - } - - public PCRERFFI getPCRERFFI() { - throw missing("PCRE"); - } - - public ZipRFFI getZipRFFI() { - throw missing("Zip"); - } - - private static RuntimeException missing(String ffi) throws RuntimeException { - throw Utils.rSuicide(ffi + " FFI not implemented"); - } - - public abstract ContextState newContext(RContext context); + public abstract ContextState newContextState(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UserRngRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UserRngRFFI.java index b3b7dc0dc3eb98c14bad2cc40154a93d2c95b23f..dc692727fcfe6b46100e854a859d63ec0abaa700 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UserRngRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UserRngRFFI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,13 +23,10 @@ package com.oracle.truffle.r.runtime.ffi; /** - * Explicit statically typed interface to user-supplied random number generators. TODO This could - * eventually be subsumed by {@link CRFFI}. + * Explicit statically typed interface to user-supplied random number generators. */ public interface UserRngRFFI { - void setLibrary(String path); - void init(int seed); double rand(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java index a6b88ffe667a4f7a9fb538496fefb7f378330435..dc99a9ddb7a8e116cb0023e4084e7f45b16f82e1 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -30,13 +30,13 @@ public interface ZipRFFI { * * @return standard return code (0 ok) */ - int compress(byte[] dest, long[] destlen, byte[] source); + int compress(byte[] dest, byte[] source); /** * uncompress {@code source} into {@code dest}. * * @return standard return code (0 ok) */ - int uncompress(byte[] dest, long[] destlen, byte[] source); + int uncompress(byte[] dest, byte[] source); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java index 09f5a10046d079cd9b7697e1d51e4fb172fb4556..4af3bde56a12da075ef32fb01242f384c846c925 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java @@ -22,21 +22,26 @@ */ package com.oracle.truffle.r.runtime.instrument; -import java.io.PrintWriter; +import java.io.PrintStream; +import java.util.ArrayList; import java.util.HashSet; +import java.util.Map; import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.instrumentation.EventBinding; import com.oracle.truffle.api.instrumentation.ExecutionEventListener; import com.oracle.truffle.api.instrumentation.Instrumenter; import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.api.vm.PolyglotEngine; +import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.RCleanUp; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.tools.Profiler; /** - * The tracingState is a global variable in R, so we store it (and the associated listener objects) - * in the {@link RContext}. We also store related {@code debug} state, as that is also context - * specific. + * Collects together all the context-specific state related to profiling, instrumentation. * */ public final class InstrumentationState implements RContext.ContextState { @@ -63,12 +68,9 @@ public final class InstrumentationState implements RContext.ContextState { */ private Profiler profiler; - /** - * The {@link RprofState} state, if any, associated with this {@link RContext}. - */ - private final RprofState rprofState; + private TracememContext tracememContext; - private final TracememContext tracememContext; + Map<String, RprofState> rprofStates = new ConcurrentHashMap<>(7); /** * State used by the {@code tracemem} built-in. @@ -87,7 +89,7 @@ public final class InstrumentationState implements RContext.ContextState { /** * The {@link BrowserState} state, if any, associated with this {@link RContext}. */ - private final BrowserState browserState; + private BrowserState browserState; /** * Whether debugging is globally disabled in this {@link RContext}. Used to (temporarily) @@ -96,58 +98,53 @@ public final class InstrumentationState implements RContext.ContextState { */ private boolean debugGloballyDisabled; - /** - * State used by {@code Rprof}. - * - */ - public static final class RprofState { - private PrintWriter out; - private Thread profileThread; - private ExecutionEventListener statementListener; - private long intervalInMillis; - private boolean lineProfiling; + public abstract static class RprofState implements CleanupHandler { + private PrintStream out; - public void initialize(PrintWriter outA, Thread profileThreadA, ExecutionEventListener statementListenerA, long intervalInMillisA, - boolean lineProfilingA) { - this.out = outA; - this.profileThread = profileThreadA; - this.statementListener = statementListenerA; - this.intervalInMillis = intervalInMillisA; - this.lineProfiling = lineProfilingA; + protected RprofState() { + RCleanUp.registerCleanupHandler(this); } - public boolean lineProfiling() { - return lineProfiling; - } - - public PrintWriter out() { + /** + * Return current output or {@code null} if not profiling. + */ + public PrintStream out() { return out; } - public long intervalInMillis() { - return intervalInMillis; - } - - public ExecutionEventListener statementListener() { - return statementListener; + public void setOut(PrintStream out) { + this.out = out; } - public Thread profileThread() { - return profileThread; + public void closeAndResetOut() { + out.flush(); + out.close(); + out = null; } - } public static class BrowserState { - private boolean inBrowser; + public static final class HelperState { + // docs state that "text" is a string but in reality it can be anything + public final Object text; + public final Object condition; + + public HelperState(Object text, Object condition) { + this.text = text; + this.condition = condition; + } + } + + private RCaller caller; private String lastEmptyLineCommand = "n"; + private ArrayList<HelperState> helperStateList = new ArrayList<>(); - public void setInBrowser(boolean state) { - this.inBrowser = state; + public void setInBrowser(RCaller caller) { + this.caller = caller; } public boolean inBrowser() { - return inBrowser; + return caller != null; } public void setLastEmptyLineCommand(String s) { @@ -157,27 +154,61 @@ public final class InstrumentationState implements RContext.ContextState { public String lastEmptyLineCommand() { return lastEmptyLineCommand; } + + public RCaller getInBrowserCaller() { + return caller; + } + + @TruffleBoundary + public void push(HelperState helperState) { + helperStateList.add(helperState); + } + + @TruffleBoundary + public void pop() { + helperStateList.remove(helperStateList.size() - 1); + } + + @TruffleBoundary + public HelperState get(int n) { + int nn = n; + if (nn > helperStateList.size()) { + nn = helperStateList.size(); + } + return helperStateList.get(nn - 1); + } + + } + + /** + * An interface that can be used to register an action to be taken when the system shuts down as + * part of the {@code R_Cleanup}. + * + */ + public interface CleanupHandler { + void cleanup(int status); } private InstrumentationState(Instrumenter instrumenter) { this.instrumenter = instrumenter; - this.rprofState = new RprofState(); - this.tracememContext = new TracememContext(); - this.browserState = new BrowserState(); } + @TruffleBoundary public void putTraceBinding(SourceSection ss, EventBinding<?> binding) { traceBindingMap.put(ss, binding); } + @TruffleBoundary public EventBinding<?> getTraceBinding(SourceSection ss) { return traceBindingMap.get(ss); } + @TruffleBoundary public void putDebugListener(SourceSection ss, ExecutionEventListener listener) { debugListenerMap.put(ss, listener); } + @TruffleBoundary public EventBinding<?>[] getTraceBindings() { EventBinding<?>[] result = new EventBinding<?>[traceBindingMap.size()]; traceBindingMap.values().toArray(result); @@ -185,6 +216,7 @@ public final class InstrumentationState implements RContext.ContextState { } + @TruffleBoundary public ExecutionEventListener getDebugListener(SourceSection ss) { return debugListenerMap.get(ss); } @@ -199,11 +231,11 @@ public final class InstrumentationState implements RContext.ContextState { return tracingState; } - public void setProfiler(Profiler profiler) { - this.profiler = profiler; - } - public Profiler getProfiler() { + if (profiler == null) { + PolyglotEngine vm = RContext.getInstance().getVM(); + profiler = Profiler.find(vm); + } return profiler; } @@ -211,15 +243,28 @@ public final class InstrumentationState implements RContext.ContextState { return instrumenter; } - public RprofState getRprof() { - return rprofState; + @TruffleBoundary + public RprofState getRprofState(String name) { + RprofState state = rprofStates.get(name); + return state; + } + + @TruffleBoundary + public void setRprofState(String name, RprofState state) { + rprofStates.put(name, state); } public TracememContext getTracemem() { + if (tracememContext == null) { + tracememContext = new TracememContext(); + } return tracememContext; } public BrowserState getBrowserState() { + if (browserState == null) { + browserState = new BrowserState(); + } return browserState; } @@ -233,7 +278,7 @@ public final class InstrumentationState implements RContext.ContextState { return debugGloballyDisabled; } - public static InstrumentationState newContext(@SuppressWarnings("unused") RContext context, Instrumenter instrumenter) { + public static InstrumentationState newContextState(Instrumenter instrumenter) { return new InstrumentationState(instrumenter); } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsFastPath.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsFastPath.java index 7485df6bc517b694b0b08604f64d936c11506bed..82cbd61526bc10abcd5f907a17fba9583a856e24 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsFastPath.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsFastPath.java @@ -26,6 +26,7 @@ import java.util.Arrays; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.FastROptions; +import com.oracle.truffle.r.runtime.RVisibility; import com.oracle.truffle.r.runtime.builtins.FastPathFactory; final class EvaluatedArgumentsFastPath implements FastPathFactory { @@ -41,6 +42,11 @@ final class EvaluatedArgumentsFastPath implements FastPathFactory { return null; } + @Override + public RVisibility getVisibility() { + return null; + } + @Override public boolean evaluatesArgument(int index) { return false; 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 8710f1010399bb747ae40a7f0b916d9d2d5ef20c..dceb2b32f2eec9104daf8028dc90c75a21479898 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 @@ -27,7 +27,6 @@ import com.oracle.truffle.api.nodes.NodeVisitor; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RSerialize; import com.oracle.truffle.r.runtime.context.RContext; /** @@ -52,7 +51,6 @@ import com.oracle.truffle.r.runtime.context.RContext; * <li>An instance of the subclass is never used to {@link #replace} an instance of * {@link RBaseNode}.</li> * </ul> - * */ public abstract class RBaseNode extends Node { @@ -121,11 +119,6 @@ public abstract class RBaseNode extends Node { return null; } - public void serialize(RSerialize.State state) { - RSyntaxNode syntaxNode = getRSyntaxNode(); - syntaxNode.serializeImpl(state); - } - @Override public SourceSection getSourceSection() { /* diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RFastPathNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RFastPathNode.java index af5a762ce0ded699f73451fffdb63bb5a5084f59..859d2c670d46d5646566adc7fb7c65c2811465cd 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RFastPathNode.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RFastPathNode.java @@ -22,11 +22,9 @@ */ package com.oracle.truffle.r.runtime.nodes; -import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.frame.VirtualFrame; -@NodeChild(value = "arguments", type = RNode[].class) -public abstract class RFastPathNode extends RNode { +public abstract class RFastPathNode extends RBaseNode { public abstract Object execute(VirtualFrame frame, Object... args); 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 705968c91b77d672bdbac6ee8212c7130ac7a259..da9dde697b56976f26279fb8967153867df90f99 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 @@ -29,6 +29,9 @@ import com.oracle.truffle.api.source.SourceSection; */ public interface RSyntaxLookup extends RSyntaxElement { + /** + * @return The identifier that this lookup represents - this needs to be an interned string. + */ String getIdentifier(); boolean isFunctionLookup(); @@ -39,7 +42,7 @@ public interface RSyntaxLookup extends RSyntaxElement { * section. */ static RSyntaxLookup createDummyLookup(SourceSection originalSource, String identifier, boolean isFunctionLookup) { - SourceSection source = originalSource == null || originalSource.getSource() == null ? null : originalSource.getSource().createSection(null, originalSource.getCharIndex(), 1); + SourceSection source = originalSource == null || originalSource.getCharEndIndex() == 0 ? null : originalSource.getSource().createSection(originalSource.getCharIndex(), 1); return new RSyntaxLookup() { @Override public SourceSection getSourceSection() { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxNode.java index 2efdd70eaed5f94b3537c63b5b4613335629b68e..6c98f726f1053574032828c8f8eaa7e476bc33db 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxNode.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxNode.java @@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime.nodes; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.context.RContext; /** @@ -52,12 +53,8 @@ import com.oracle.truffle.r.runtime.context.RContext; * {@link #SOURCE_UNAVAILABLE}, that can be used instead of {@code null} and identify the situation. * One particular case is {@link #LAZY_DEPARSE} which indicates that a valid {@link SourceSection} * can be produced for the associated node, but it is computed lazily, when requested. - * - * Every implementor of this interface must provide an implementation of the {@link #serializeImpl} - * method. These are invoked by the corresponding method on {@link RBaseNode} after the correct - * {@link RSyntaxNode} is located. */ -public interface RSyntaxNode extends RSyntaxNodeSPI, RSyntaxElement { +public interface RSyntaxNode extends RSyntaxElement { /** * A convenience method that captures the fact that, while the notion of a syntax node is @@ -87,26 +84,26 @@ public interface RSyntaxNode extends RSyntaxNodeSPI, RSyntaxElement { * Indicates the case where a node that should have a valid {@link SourceSection} but for reason * does not have. Ideally never required. */ - SourceSection SOURCE_UNAVAILABLE = SourceSection.createUnavailable("R", "unavailable"); + SourceSection SOURCE_UNAVAILABLE = RSource.createUnknown("unavailable"); /** * Indicates a node that was created as part of an AST transformation related to the internal * execution process. This should never be used for a node that could manifest to the R * programmer. */ - SourceSection INTERNAL = SourceSection.createUnavailable("R", "internal"); + SourceSection INTERNAL = RSource.createUnknown("internal"); /** * Indicates that this {@link SourceSection} can be created on demand if required. */ - SourceSection LAZY_DEPARSE = SourceSection.createUnavailable("R", "lazy deparse"); + SourceSection LAZY_DEPARSE = RSource.createUnknown("lazy deparse"); /** * Indicates that, after creating the node, which requires a non-null {@link SourceSection} it * should be created and updated by deparsing. This is generally used in specific situations, * e.g., the {@code substitute} builtin. */ - SourceSection EAGER_DEPARSE = SourceSection.createUnavailable("R", "eager deparse"); + SourceSection EAGER_DEPARSE = RSource.createUnknown("eager deparse"); /* * Every implementor of this interface must either inherit or directly implement the following diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxNodeSPI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/TruffleBiFunction.java similarity index 61% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxNodeSPI.java rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/TruffleBiFunction.java index d194650ae62161adc734931f0cdab3ea00fef6ec..43abb1a57b1bcbefd6a6e23814657901ab4ac115 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxNodeSPI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/TruffleBiFunction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -22,21 +22,23 @@ */ package com.oracle.truffle.r.runtime.nodes; -import com.oracle.truffle.r.runtime.RSerialize; -import com.oracle.truffle.r.runtime.RSerialize.State; +import java.util.function.BiFunction; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; /** - * The following methods must be implemented by all implementors of {@link RSyntaxNode}. However, - * they should not, in general, be called, unless it is statically known that the node is an - * {@link RSyntaxNode}. Instead the generic methods on {@link RBaseNode} should be called. - * + * A slight variant of {@link BiFunction} that produces better call graph analysis of methods that + * need {@link TruffleBoundary} annotations. */ -interface RSyntaxNodeSPI { - +@FunctionalInterface +public interface TruffleBiFunction<T, U, R> { /** - * Support for serializing closures. The relevant methods in {@link State} should be called to - * create the virtual pairlist for this node, + * Applies this function to the given arguments. + * + * @param t the first function argument + * @param u the second function argument + * @return the function result */ - void serializeImpl(RSerialize.State state); + R apply(T t, U u); } 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 e7cfa312c1d4f277d0e77f4b3bcf2345324f192a..c83d7f930d9a00ae91f6dfed3e1b65d78bc83437 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 @@ -29,6 +29,7 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.profiles.BranchProfile; 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.RComplex; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RNull; @@ -195,6 +196,8 @@ public final class NACheck { if (checkNAorNaN(value)) { // Special case here NaN does not enable the NA check. this.enable(true); + // Note: GnuR seems to convert NaN to NaN + 0i and NA to NA, but doing it here breaks + // other things return RRuntime.createComplexNA(); } return RDataFactory.createComplex(value, 0); @@ -271,14 +274,14 @@ public final class NACheck { if (check(value)) { return RRuntime.STRING_NA; } - return RRuntime.doubleToStringNoCheck(value); + return RContext.getRRuntimeASTAccess().encodeDouble(value); } public String convertComplexToString(RComplex value) { if (check(value)) { return RRuntime.STRING_NA; } - return RRuntime.complexToStringNoCheck(value); + return RContext.getRRuntimeASTAccess().encodeComplex(value); } public double convertComplexToDouble(RComplex value, boolean warning) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java index 3a6e356fcfaeb38539cacd10aeade9d1bf823d61..88742c519159680226051c8df374addd89f4e25f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java @@ -128,11 +128,19 @@ public class RRNG { private final RandomNumberGenerator[] allGenerators; private NormKind currentNormKind; - private ContextStateImpl(RandomNumberGenerator rng, NormKind currentNormKind) { - this.currentGenerator = rng; - this.currentNormKind = currentNormKind; + private ContextStateImpl() { + this.currentNormKind = DEFAULT_NORM_KIND; this.allGenerators = new RandomNumberGenerator[Kind.VALUES.length]; + } + + @Override + public RContext.ContextState initialize(RContext context) { + int seed = timeToSeed(); + RandomNumberGenerator rng = DEFAULT_KIND.create(); + initGenerator(rng, seed); + this.currentGenerator = rng; this.allGenerators[rng.getKind().ordinal()] = rng; + return this; } /* @@ -180,11 +188,8 @@ public class RRNG { } } - public static ContextStateImpl newContext(@SuppressWarnings("unused") RContext context) { - int seed = timeToSeed(); - RandomNumberGenerator rng = DEFAULT_KIND.create(); - initGenerator(rng, seed); - return new ContextStateImpl(rng, DEFAULT_NORM_KIND); + public static ContextStateImpl newContextState() { + return new ContextStateImpl(); } } @@ -286,7 +291,7 @@ public class RRNG { } private static Kind intToKind(int kindAsInt) { - if (kindAsInt < 0 || kindAsInt >= Kind.VALUES.length) { + if (kindAsInt < 0 || kindAsInt >= Kind.VALUES.length || !Kind.VALUES[kindAsInt].isAvailable()) { throw RError.error(RError.NO_CALLER, RError.Message.RNG_NOT_IMPL_KIND, kindAsInt); } return Kind.VALUES[kindAsInt]; 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 bc649e2415f24676d88609143feee3c1f02631ab..9e1f745d769433b28be59b45398e497348bf8cce 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 @@ -35,42 +35,68 @@ import com.oracle.truffle.r.runtime.rng.RRNG.Kind; * Interface to a user-supplied RNG. */ public final class UserRNG extends RNGInitAdapter { - - private static final String USER_UNIF_RAND = "user_unif_rand"; - private static final String USER_UNIF_INIT = "user_unif_init"; private static final boolean OPTIONAL = true; - @SuppressWarnings("unused") private long userUnifRand; - @SuppressWarnings("unused") private long userUnifInit; - private long userUnifNSeed; - private long userUnifSeedloc; + public enum Function { + Rand(!OPTIONAL), + Init(OPTIONAL), + NSeed(OPTIONAL), + Seedloc(OPTIONAL); + + private long address; + private final String symbol; + private final boolean optional; + + Function(boolean optional) { + this.symbol = "user_unif_" + name().toLowerCase(); + this.optional = optional; + } + + private boolean isDefined() { + return address != 0; + } + + public long getAddress() { + return address; + } + + private void setAddress(DLLInfo dllInfo) { + this.address = findSymbol(symbol, dllInfo, optional); + } + + } + private UserRngRFFI userRngRFFI; private int nSeeds = 0; @Override @TruffleBoundary public void init(int seed) { - DLLInfo dllInfo = DLL.findLibraryContainingSymbol(USER_UNIF_RAND); + DLLInfo dllInfo = DLL.findLibraryContainingSymbol(Function.Rand.symbol); if (dllInfo == null) { - throw RError.error(RError.NO_CALLER, RError.Message.RNG_SYMBOL, USER_UNIF_RAND); + throw RError.error(RError.NO_CALLER, RError.Message.RNG_SYMBOL, Function.Rand.symbol); + } + for (Function f : Function.values()) { + f.setAddress(dllInfo); } - userUnifRand = findSymbol(USER_UNIF_RAND, dllInfo, !OPTIONAL); - userUnifInit = findSymbol(USER_UNIF_INIT, dllInfo, OPTIONAL); - userUnifNSeed = findSymbol(USER_UNIF_INIT, dllInfo, OPTIONAL); - userUnifSeedloc = findSymbol(USER_UNIF_INIT, dllInfo, OPTIONAL); userRngRFFI = RFFIFactory.getRFFI().getUserRngRFFI(); - userRngRFFI.setLibrary(dllInfo.path); - userRngRFFI.init(seed); - if (userUnifSeedloc != 0 && userUnifNSeed == 0) { + if (Function.Init.isDefined()) { + userRngRFFI.init(seed); + } + if (Function.Seedloc.isDefined() && !Function.NSeed.isDefined()) { RError.warning(RError.NO_CALLER, RError.Message.RNG_READ_SEEDS); } - int ns = userRngRFFI.nSeed(); - if (ns < 0 || ns > 625) { - RError.warning(RError.NO_CALLER, RError.Message.GENERIC, "seed length must be in 0...625; ignored"); - } else { - nSeeds = ns; - // TODO: if we ever (initially) share iSeed (as GNU R does) we may need to assign this - // generator's iSeed here + if (Function.NSeed.isDefined()) { + int ns = userRngRFFI.nSeed(); + if (ns < 0 || ns > 625) { + RError.warning(RError.NO_CALLER, RError.Message.GENERIC, "seed length must be in 0...625; ignored"); + } else { + nSeeds = ns; + /* + * TODO: if we ever (initially) share iSeed (as GNU R does) we may need to assign + * this generator's iSeed here + */ + } } } @@ -95,7 +121,7 @@ public final class UserRNG extends RNGInitAdapter { @Override public int[] getSeeds() { - if (userUnifSeedloc == 0) { + if (!Function.Seedloc.isDefined()) { return null; } int[] result = new int[nSeeds]; diff --git a/com.oracle.truffle.r.test.cran/r/install.cran.packages.R b/com.oracle.truffle.r.test.cran/r/install.cran.packages.R index 097eab15f6bf8feeb4576609efce8337a4fd018b..8cf210cda483b9f05b0f9b09d7fab2fce9463c86 100644 --- a/com.oracle.truffle.r.test.cran/r/install.cran.packages.R +++ b/com.oracle.truffle.r.test.cran/r/install.cran.packages.R @@ -91,6 +91,7 @@ usage <- function() { "[--testdir dir]", "[--print-ok-installs]", "[--list-versions]", + "[--list-canonical]", "[--use-installed-pkgs]", "[--invert-pkgset]", "[--alpha-daily]", @@ -522,7 +523,9 @@ do.it <- function() { if (list.versions) { for (pkgname in test.pkgnames) { pkg <- toinstall.pkgs[pkgname, ] - cat(pkg["Package"], pkg["Version"], paste0(contriburl, "/", pkg["Version"], ".tar.gz"), "\n", sep=",") + # pretend we are acessing CRAN if list.canonical + list.contriburl = ifelse(list.canonical, "https://cran.r-project.org/src/contrib", contriburl) + cat(pkg["Package"], pkg["Version"], paste0(list.contriburl, "/", pkgname, "_", pkg["Version"], ".tar.gz"), "\n", sep=",") } } @@ -608,7 +611,7 @@ install.pkg <- function(pkgname) { system.install <- function(pkgname) { script <- normalizePath("com.oracle.truffle.r.test.cran/r/install.package.R") if (is.fastr()) { - rscript = normalizePath("bin/Rscript") + rscript = file.path(R.home(), "bin", "Rscript") } else { rscript = "Rscript" } @@ -652,7 +655,7 @@ is.fastr <- function() { system.test <- function(pkgname) { script <- normalizePath("com.oracle.truffle.r.test.cran/r/test.package.R") if (is.fastr()) { - rscript = normalizePath("bin/Rscript") + rscript = file.path(R.home(), "bin", "Rscript") } else { rscript = "Rscript" } @@ -734,6 +737,8 @@ parse.args <- function() { print.install.status <<- T } else if (a == "--list-versions") { list.versions <<- TRUE + } else if (a == "--list-canonical") { + list.canonical <<- TRUE } else if (a == "--install-dependents-first") { install.dependents.first <<- TRUE } else if (a == "--use-installed-pkgs") { @@ -859,6 +864,7 @@ run.mode <- "system" run.tests <- FALSE gnur <- FALSE list.versions <- FALSE +list.canonical <- FALSE invert.pkgset <- F if (!interactive()) { diff --git a/com.oracle.truffle.r.test.native/Makefile b/com.oracle.truffle.r.test.native/Makefile index 37c62d9a92a3bb060854303ab453afc9647cdf88..d996da3e45a82598ff2e6d117305549b4308e679 100644 --- a/com.oracle.truffle.r.test.native/Makefile +++ b/com.oracle.truffle.r.test.native/Makefile @@ -24,6 +24,8 @@ .PHONY: all clean 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) OSNAME := $(shell uname) all: diff --git a/com.oracle.truffle.r.test.native/packages/Makefile b/com.oracle.truffle.r.test.native/packages/Makefile index 7b14f9a4fb9e5f580b46fa3938a0d3d051343979..1ddf9d6a2f99f41a0887e1a39f09b52ce6003eb1 100644 --- a/com.oracle.truffle.r.test.native/packages/Makefile +++ b/com.oracle.truffle.r.test.native/packages/Makefile @@ -21,21 +21,39 @@ # questions. # -.PHONY: all clean make_subdirs clean_subdirs +.PHONY: all clean make_subdirs clean_subdirs clean_recommended -SUBDIRS = testrffi vanilla +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) +GNUR_RECOMMENDED := $(wildcard $(GNUR_HOME)/src/library/Recommended/*.tgz) -all: make_subdirs +# We have to copy the GNU R recommended packages into this project +# to keep the mx archiver happy, which asserts that every path +# is inside the project. + +# WARNING: If you add/delete anything in this project you must update mx_fastr_dists.py +# to reflect the changes, e.g., adding a new SUBDIR + +all: make_subdirs copy_recommended make_subdirs: for dir in $(SUBDIRS); do \ $(MAKE) PACKAGE=$$dir -C $$dir || exit 1; \ done -clean: clean_subdirs +copy_recommended: + mkdir -p recommended + cp $(GNUR_RECOMMENDED) recommended + touch copy_recommended + +clean: clean_subdirs clean_recommended clean_subdirs: for dir in $(SUBDIRS); do \ $(MAKE) PACKAGE=$$dir -C $$dir clean || exit 1; \ done +clean_recommended: + rm -rf recommended copy_recommended diff --git a/com.oracle.truffle.r.test.native/packages/package.mk b/com.oracle.truffle.r.test.native/packages/package.mk index 27379351e2103080b21be98a43d4da93ed2d54fc..c7e7565abc99b8920745a11e406654b0bbaecda7 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, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 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 diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R index 767a8c3cbcd9b43a42eed4a917dcaba28353adaf..6f53923b5377add006be17e501fd321463e2ffff 100644 --- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R @@ -30,8 +30,8 @@ rffi.TYPEOF <- function(x) { .Call("invoke_TYPEOF", x, PACKAGE = "testrffi") } -rffi.error <- function() { - .Call("invoke_error", PACKAGE = "testrffi") +rffi.error <- function(msg = "invoke_error in testrffi") { + .Call("invoke_error", msg, PACKAGE = "testrffi") } rffi.dotExternalAccessArgs <- function(...) { @@ -95,3 +95,18 @@ rffi.iterate_iptr <- function(x) { .Call("iterate_iptr", x, PACKAGE = "testrffi") } +rffi.preserve_object <- function() { + .Call("preserve_object", PACKAGE = "testrffi") +} + +rffi.release_object <- function(x) { + invisible(.Call("release_object", x, PACKAGE = "testrffi")) +} + +rffi.findvar <- function(x, env) { + if (is.character(x)) { + x = as.symbol(x) + } + .Call("findvar", x, env, PACKAGE = "testrffi") +} + diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c index 0d6d6674ffcd3812a1b859494df934aebf536b1c..61f4862f88ee9e9ae9ea2f93e8c919517571f6c5 100644 --- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c @@ -89,8 +89,8 @@ SEXP invoke_TYPEOF(SEXP x) { return ScalarInteger(TYPEOF(x)); } -SEXP invoke_error() { - error("invoke_error in testrffi"); +SEXP invoke_error(SEXP msg) { + error(R_CHAR(STRING_ELT(msg, 0))); } // returns a @@ -258,3 +258,25 @@ SEXP iterate_iptr(SEXP x) { UNPROTECT(1); return v; } + +SEXP preserve_object(void) { + SEXP v; + v = allocVector(INTSXP, 1); + R_PreserveObject(v); + return v; +} + +SEXP release_object(SEXP x) { + R_ReleaseObject(x); + return R_NilValue; +} + +SEXP findvar(SEXP x, SEXP env) { + SEXP v = Rf_findVar(x, env); + if (v == R_UnboundValue) { + Rf_error("'%s' not found", R_CHAR(PRINTNAME(x))); + } else { + return v; + } +} + diff --git a/com.oracle.truffle.r.test.native/packages/tests4/lib/tests4.tar b/com.oracle.truffle.r.test.native/packages/tests4/lib/tests4.tar deleted file mode 100644 index 914271602ff2cbf7c620962cffc565d300fc4d8b..0000000000000000000000000000000000000000 Binary files a/com.oracle.truffle.r.test.native/packages/tests4/lib/tests4.tar and /dev/null differ diff --git a/com.oracle.truffle.r.test.native/urand/Makefile b/com.oracle.truffle.r.test.native/urand/Makefile index c6cd2ef26ca74924c02dab4eaff90dd0fa6d6c93..4883c2383ea1d865cf9602546081a0ac6d4751b9 100644 --- a/com.oracle.truffle.r.test.native/urand/Makefile +++ b/com.oracle.truffle.r.test.native/urand/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. +# 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 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 5774cdbc65dcccdf4aaaaafad70e30ee0e9d1813..f2d2e23fb007f43449bc76abe0091e3837d0ef14 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,5 +1,5 @@ ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation1.R") } +#{ 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" @@ -9,44 +9,44 @@ Slot "age": ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation10.R") } +#{ 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.TestS4.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation2.R") } +#{ 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.TestS4.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation3.R") } +#{ 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.TestS4.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation4.R") } +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation4.R") } numeric(0) ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation5.R") } +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation5.R") } numeric(0) ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation6.R") } +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation6.R") } [1] NA ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation7.R") } +#{ 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 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation8.R") } +#{ 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 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation9.R") } +#{ 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" @@ -56,7 +56,7 @@ Slot "age": ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods1.R") } +#{ 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" @@ -72,7 +72,7 @@ description class mode text opened can read "yes" ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods2.R") } +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/methods2.R") } Function: sides (package .GlobalEnv) object="Polygon" @@ -86,12 +86,12 @@ description class mode text opened can read "yes" ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods3.R") } +#{ 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.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods4.R") } +#{ 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 @@ -99,13 +99,13 @@ Note: method with signature ‘A2#A1’ chosen for function ‘foo’, [1] "2-1" ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods5.R") } +#{ 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.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/slot_access1.R") } +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/slot_access1.R") } name age "character" "numeric" @@ -158,7 +158,7 @@ Class: numeric #{ gen<-function(object) 0; setGeneric("gen"); res<-print(gen); removeGeneric("gen"); res } function (object) standardGeneric("gen") -<environment: 0x7f8e1e9262d8> +<environment: 0x7fef52953038> attr(,"generic") [1] "gen" attr(,"generic")attr(,"package") @@ -192,7 +192,7 @@ standardGeneric for "gen" defined from package ".GlobalEnv" function (object) standardGeneric("gen") -<environment: 0x7f8e1e9262d8> +<environment: 0x7fef52953038> Methods may be defined for arguments: object Use showMethods("gen") for currently available ones. @@ -219,7 +219,7 @@ Creating a generic function for ‘diag<-’ from package ‘base’ in the glob ##com.oracle.truffle.r.test.S4.TestS4.testMethods #{ setGeneric("gen", function(object) standardGeneric("gen")); res<-print(gen); removeGeneric("gen"); res } function(object) standardGeneric("gen") -<environment: 0x7fa19ba4b180> +<environment: 0x7fc92a1a12e0> attr(,"generic") [1] "gen" attr(,"generic")attr(,"package") @@ -246,7 +246,7 @@ standardGeneric for "gen" defined from package ".GlobalEnv" function (object) standardGeneric("gen") -<environment: 0x7fa19ba4b180> +<environment: 0x7fc92a1a12e0> Methods may be defined for arguments: object Use showMethods("gen") for currently available ones. @@ -374,6 +374,29 @@ 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 +#{ standardGeneric("") } +Error in standardGeneric("") : + argument to 'standardGeneric' must be a non-empty character string + +##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric +#{ standardGeneric("foo", 42) } +Error: expected a generic function or a primitive for dispatch, got an object of class "numeric" + +##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric +#{ standardGeneric(42) } +Error in standardGeneric(42) : + argument to 'standardGeneric' must be a non-empty character string + +##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric +#{ standardGeneric(character()) } +Error in standardGeneric(character()) : + argument to 'standardGeneric' must be a non-empty character string + +##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric +#{ x<-42; class(x)<-character(); standardGeneric("foo", x) } +Error: expected a generic function or a primitive for dispatch, got an object of class "numeric" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_Arg.testArg1 #argv <- list(1+2i);Arg(argv[[1]]); [1] 1.107149 @@ -577,6 +600,10 @@ character(0) #argv <- list(structure(c(11354, 11382, 11413), class = 'Date')); .Internal(Date2POSIXlt(argv[[1]])) [1] "2001-02-01 UTC" "2001-03-01 UTC" "2001-04-01 UTC" +##com.oracle.truffle.r.test.builtins.TestBuiltin_Encoding.testEncoding +#{ x<-42; Encoding(x) } +Error in Encoding(x) : a character vector argument expected + ##com.oracle.truffle.r.test.builtins.TestBuiltin_Encoding.testEncoding1 #argv <- list('Byte Code Compiler'); .Internal(Encoding(argv[[1]])) [1] "unknown" @@ -612,6 +639,26 @@ character(0) #argv <- structure(list(x = 'abc'), .Names = 'x');do.call('Encoding', argv) [1] "unknown" +##com.oracle.truffle.r.test.builtins.TestBuiltin_Encodingassign_.testEncoding +#{ x<-"foo"; Encoding(x)<-42 } +Error in `Encoding<-`(`*tmp*`, value = 42) : + a character vector 'value' expected + +##com.oracle.truffle.r.test.builtins.TestBuiltin_Encodingassign_.testEncoding +#{ x<-"foo"; Encoding(x)<-NULL } +Error in `Encoding<-`(`*tmp*`, value = NULL) : + a character vector 'value' expected + +##com.oracle.truffle.r.test.builtins.TestBuiltin_Encodingassign_.testEncoding +#{ x<-"foo"; Encoding(x)<-character() } +Error in `Encoding<-`(`*tmp*`, value = character(0)) : + 'value' must be of positive length + +##com.oracle.truffle.r.test.builtins.TestBuiltin_Encodingassign_.testEncoding +#{ x<-42; Encoding(x)<-"UTF-8" } +Error in `Encoding<-`(`*tmp*`, value = "UTF-8") : + a character vector argument expected + ##com.oracle.truffle.r.test.builtins.TestBuiltin_Encodingassign_.testEncodingassign_1 #argv <- structure(list(x = 'abc', value = 'UTF-8'), .Names = c('x', 'value'));do.call('Encoding<-', argv) [1] "abc" @@ -622,7 +669,15 @@ character(0) ##com.oracle.truffle.r.test.builtins.TestBuiltin_ISOdatetime.testISOdatetime2 #argv <- structure(list(year = 2002, month = 6, day = 24, hour = 0, min = 0, sec = 10), .Names = c('year', 'month', 'day', 'hour', 'min', 'sec'));do.call('ISOdatetime', argv) -[1] "2002-06-24 00:00:10 CEST" +[1] "2002-06-24 00:00:10 GMT" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_Im.testIm +#Im(NaN) +[1] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_Im.testIm +#Im(c(NaN, 1+1i)) +[1] 0 1 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Im.testIm #{ Im(1) } @@ -778,7 +833,7 @@ $pivot Intercept -0.2236068 -0.6708204 X 0.0000000 0.4472136 -##com.oracle.truffle.r.test.builtins.TestBuiltin_La.testLa3 +##com.oracle.truffle.r.test.builtins.TestBuiltin_La.testLa3a #argv <- list(structure(c(-21.2222451396881, 306.936914624821, 0, 0, 0, -101.353437863947, -21.2222451396881, 0, 0, 0, 45.8768670002026, 63.2672432400162, -11.7486843755171, 0, 0, 65.1621918666428, 125.787781278037, -111.869521123473, 61.0965873274467, -54.389932439947, -26.0785375270079, -209.347244886481, 112.817924425406, 108.385517228532, 61.0965873274467), .Dim = c(5L, 5L), .Dimnames = list(NULL, NULL)), FALSE); .Internal(La_rg(argv[[1]], argv[[2]])) $values [1] -21.22225+176.37775i -21.22225-176.37775i -11.74868+ 0.00000i @@ -799,6 +854,16 @@ $vectors [5,] 0.3297248-0.0460577i 0.3297248+0.0460577i +##com.oracle.truffle.r.test.builtins.TestBuiltin_La.testLa3b +#argv <- list(structure(c(-21.2222451396881, 306.936914624821, 0, 0, 0, -101.353437863947, -21.2222451396881, 0, 0, 0, 45.8768670002026, 63.2672432400162, -11.7486843755171, 0, 0, 65.1621918666428, 125.787781278037, -111.869521123473, 61.0965873274467, -54.389932439947, -26.0785375270079, -209.347244886481, 112.817924425406, 108.385517228532, 61.0965873274467), .Dim = c(5L, 5L), .Dimnames = list(NULL, NULL)), TRUE); .Internal(La_rg(argv[[1]], argv[[2]])) +$values +[1] -21.22225+176.37775i -21.22225-176.37775i -11.74868+ 0.00000i +[4] 61.09659+ 76.77943i 61.09659- 76.77943i + +$vectors +NULL + + ##com.oracle.truffle.r.test.builtins.TestBuiltin_La.testLa4 #argv <- list('S', structure(c(1, 0, 0, 0, 0, 1.4142135623731, 0, 0, 0, 0, 1.73205080756888, 0, 0, 0, 0, 2), .Dim = c(4L, 4L), Dimnames = list(character(0), character(0))), c(2, 1.73205080756888, 1.4142135623731, 1), structure(c(0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0), .Dim = c(4L, 4L)), structure(c(0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0), .Dim = c(4L, 4L))); .Internal(La_svd(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) $d @@ -923,6 +988,18 @@ $vt [14,] 2.934442e-02 0.0499572846 -2.117797e-02 1.755687e-01 1.567252e-01 [15,] 1.370608e-03 0.0972526870 -4.824705e-02 1.567252e-01 2.687664e-01 +##com.oracle.truffle.r.test.builtins.TestBuiltin_La.testMisc +#{ .Internal(La_solve(structure(c(2,1)), structure(c(1, 0, 0, 1), .Dim = c(2L, 2L)), 2.22044604925031e-16)) } +Error: 'a' must be a numeric matrix + +##com.oracle.truffle.r.test.builtins.TestBuiltin_La.testMisc +#{ .Internal(La_solve(structure(c(2,1), .Dim = c(2,1)), structure(c(1, 0, 0, 1), .Dim = c(2L, 2L)), 2.22044604925031e-16)) } +Error: 'a' (2 x 1) must be square + +##com.oracle.truffle.r.test.builtins.TestBuiltin_La.testMisc +#{ .Internal(La_solve(structure(numeric(0), .Dim = c(0,0)), structure(c(1, 0, 0, 1), .Dim = c(2L, 2L)), 2.22044604925031e-16)) } +Error: 'a' is 0-diml + ##com.oracle.truffle.r.test.builtins.TestBuiltin_La.testMisc #{ x<-matrix(1:4, ncol=2); solve(x) } [,1] [,2] @@ -934,8 +1011,8 @@ $vt Error in Mod(as.raw(12)) : non-numeric argument to function ##com.oracle.truffle.r.test.builtins.TestBuiltin_Mod.testMod -#{ is.integer(Mod(FALSE) } -Error: unexpected '}' in "{ is.integer(Mod(FALSE) }" +#{ is.integer(Mod(FALSE)) } +[1] FALSE ##com.oracle.truffle.r.test.builtins.TestBuiltin_Mod.testMod #{ round(Mod(1+1i)*10000) } @@ -1101,10 +1178,58 @@ character(0) #argv <- list(structure(list(sec = c(0, 0, 0, 0, 0), min = c(0L, 0L, 0L, 0L, 0L), hour = c(0L, 0L, 0L, 0L, 0L), mday = 22:26, mon = c(3L, 3L, 3L, 3L, 3L), year = c(108L, 108L, 108L, 108L, 108L), wday = 2:6, yday = 112:116, isdst = c(-1L, -1L, -1L, -1L, -1L)), .Names = c('sec', 'min', 'hour', 'mday', 'mon', 'year', 'wday', 'yday', 'isdst'), class = c('POSIXlt', 'POSIXt'), tzone = 'GMT')); .Internal(POSIXlt2Date(argv[[1]])) [1] "2008-04-22" "2008-04-23" "2008-04-24" "2008-04-25" "2008-04-26" +##com.oracle.truffle.r.test.builtins.TestBuiltin_Primitive.testPrimitive1 +#.Primitive('any') +function (..., na.rm = FALSE) .Primitive("any") + +##com.oracle.truffle.r.test.builtins.TestBuiltin_Primitive.testPrimitive1 +#.Primitive('complex') +Error in .Primitive("complex") : no such primitive function + +##com.oracle.truffle.r.test.builtins.TestBuiltin_Primitive.testPrimitive1 +#.Primitive('foo') +Error in .Primitive("foo") : no such primitive function + +##com.oracle.truffle.r.test.builtins.TestBuiltin_Primitive.testPrimitive1 +#.Primitive(1) +Error in .Primitive(1) : string argument required + +##com.oracle.truffle.r.test.builtins.TestBuiltin_Primitive.testPrimitive1 +#.Primitive(c('c', 'b')) +Error in .Primitive(c("c", "b")) : string argument required + ##com.oracle.truffle.r.test.builtins.TestBuiltin_Primitive.testPrimitive1 #argv <- list('c');.Primitive(argv[[1]]); function (..., recursive = FALSE) .Primitive("c") +##com.oracle.truffle.r.test.builtins.TestBuiltin_RNGkind.testArgsCast +#.Internal(RNGkind('abc', NULL)) +Error: RNGkind: unimplemented RNG kind -2147483648 +In addition: Warning message: +NAs introduced by coercion + +##com.oracle.truffle.r.test.builtins.TestBuiltin_RNGkind.testArgsCast +#.Internal(RNGkind(1L, 1L)) +[1] 3 4 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_RNGkind.testArgsCast +#.Internal(RNGkind(NULL, 'abc')) +Error: invalid Normal type in 'RNGkind' +In addition: Warning message: +NAs introduced by coercion + +##com.oracle.truffle.r.test.builtins.TestBuiltin_RNGkind.testArgsCast +#.Internal(RNGkind(NULL, NULL)) +[1] 3 4 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_Re.testRe +#Re(NaN) +[1] NaN + +##com.oracle.truffle.r.test.builtins.TestBuiltin_Re.testRe +#Re(c(NaN, 1+1i)) +[1] NaN 1 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_Re.testRe #{ Re(1) } [1] 1 @@ -1297,6 +1422,20 @@ character(0) #argv <- structure(list(category = 'LC_TIME', locale = 'C'), .Names = c('category', 'locale'));do.call('Sys.setlocale', argv) [1] "C" +##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs +#.Internal(Sys.setlocale('3L', 'C')) +Error: invalid 'category' argument +In addition: Warning message: +NAs introduced by coercion + +##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 +#.Internal(Sys.setlocale(4, c('more', 'elements'))) +Error: invalid 'locale' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssleep.testSyssleep1 #argv <- list(0.5); .Internal(Sys.sleep(argv[[1]])) @@ -1475,8 +1614,8 @@ Error in abs(NULL) : non-numeric argument to mathematical function [1] 1 2 3 ##com.oracle.truffle.r.test.builtins.TestBuiltin_abs.testAbs -#{ is.integer(abs(FALSE) } -Error: unexpected '}' in "{ is.integer(abs(FALSE) }" +#{ is.integer(abs(FALSE)) } +[1] TRUE ##com.oracle.truffle.r.test.builtins.TestBuiltin_abs.testabs1 #argv <- list(c(0.9, 0.1, 0.3, 0.5, 0.7, 0.9, 0.1, 0.3, 0.5));abs(argv[[1]]); @@ -1867,6 +2006,30 @@ attr(,"trafos") #argv <- list(list(), list(), structure(c(1, 1, 1), .Names = c('insertions', 'deletions', 'substitutions')), FALSE, TRUE, FALSE, FALSE, FALSE); .Internal(adist(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]])) <0 x 0 matrix> +##com.oracle.truffle.r.test.builtins.TestBuiltin_agrep.testAgrep +#{ .Internal(agrep("7", 42, F, F, NULL, NULL, F, F)) } +Error: invalid 'x' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_agrep.testAgrep +#{ .Internal(agrep(7, "42", F, F, NULL, NULL, F, F)) } +Error: invalid 'pattern' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_agrep.testAgrep +#{ .Internal(agrep(character(), "42", F, F, NULL, NULL, F, F)) } +Error: invalid 'pattern' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_agrep.testAgrep +#{ .Internal(agrepl("7", 42, F, F, NULL, NULL, F, F)) } +Error: invalid 'x' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_agrep.testAgrep +#{ .Internal(agrepl(7, "42", F, F, NULL, NULL, F, F)) } +Error: invalid 'pattern' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_agrep.testAgrep +#{ .Internal(agrepl(character(), "42", F, F, NULL, NULL, F, F)) } +Error: invalid 'pattern' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_agrep.testagrep1 #argv <- list('x86_64-linux-gnu', 'x86_64-linux-gnu', FALSE, FALSE, c(1L, 1L, 1L), c(0.1, NA, NA, NA, NA), FALSE, TRUE); .Internal(agrep(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]])) [1] 1 @@ -2058,7 +2221,7 @@ In all(argv[[1]]) : coercing argument of type 'double' to logical ##com.oracle.truffle.r.test.builtins.TestBuiltin_allequalPOSIXt.testallequalPOSIXt2 #argv <- structure(list(target = structure(1412833061.16639, class = c('POSIXct', 'POSIXt')), current = structure(list(sec = 41.1663863658905, min = 37L, hour = 1L, mday = 9L, mon = 9L, year = 114L, wday = 4L, yday = 281L, isdst = 1L, zone = 'EDT', gmtoff = -14400L), .Names = c('sec', 'min', 'hour', 'mday', 'mon', 'year', 'wday', 'yday', 'isdst', 'zone', 'gmtoff'), class = c('POSIXlt', 'POSIXt'), tzone = c('', 'EST', 'EDT'))), .Names = c('target', 'current'));do.call('all.equal.POSIXt', argv) -[1] "Mean absolute difference: 21600" +[1] "Mean absolute difference: 14400" ##com.oracle.truffle.r.test.builtins.TestBuiltin_allequalcharacter.testallequalcharacter1 #argv <- structure(list(target = structure(c('A', 'E', 'I', 'M', 'Q', 'U', 'B', 'F', 'J', 'N', 'R', 'V', 'C', 'G', 'K', 'O', 'S', 'W', 'D', 'H', 'L', 'P', 'T', 'X'), .Dim = c(6L, 4L)), current = structure(c('A', 'E', 'I', 'M', 'Q', 'U', 'B', 'F', 'J', 'N', 'R', 'V', 'C', 'G', 'K', 'O', 'S', 'W', 'D', 'H', 'L', 'P', 'T', 'X'), .Dim = c(6L, 4L))), .Names = c('target', 'current'));do.call('all.equal.character', argv) @@ -2148,14 +2311,14 @@ character(0) #{ all.names(expression(sin(x+y+x)), max.names=NULL) } character(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_allnames.testAllNames -#{ all.names(expression(sin(x+y+x)), unique=(NA) } -Error: unexpected '}' in "{ all.names(expression(sin(x+y+x)), unique=(NA) }" - ##com.oracle.truffle.r.test.builtins.TestBuiltin_allnames.testAllNames #{ all.names(expression(sin(x+y+x)), unique=F) } [1] "sin" "+" "+" "x" "y" "x" +##com.oracle.truffle.r.test.builtins.TestBuiltin_allnames.testAllNames +#{ all.names(expression(sin(x+y+x)), unique=NA) } +[1] "sin" "+" "x" "y" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_allnames.testAllNames #{ all.names(expression(sin(x+y+x)), unique=NULL) } [1] "sin" "+" "x" "y" @@ -2538,6 +2701,22 @@ In anyDuplicated.default(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = "cat") : #argv <- list(c(1.81566026854212e-304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));do.call('anyNA', argv) [1] FALSE +##com.oracle.truffle.r.test.builtins.TestBuiltin_anyNA.testanyNA2 +#anyNA(list(list(4,5,NA), 3), recursive=TRUE) +[1] TRUE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_anyNA.testanyNA2 +#anyNA(list(list(c(NA)),c(1)), recursive=FALSE) +[1] FALSE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_anyNA.testanyNA2 +#anyNA(list(list(c(NA)),c(1)), recursive=TRUE) +[1] TRUE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_anyNA.testanyNA2 +#anyNA(list(list(c(NA)),c(1)), recursive=c(FALSE,TRUE)) +[1] FALSE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testAperm #{ a = array(1:24,c(2,3,4)); b = aperm(a); c(dim(b)[1],dim(b)[2],dim(b)[3]) } [1] 4 3 2 @@ -3894,6 +4073,58 @@ NULL #argv <- list(structure(numeric(0), .Dim = c(0L, 0L))); .Internal(args(argv[[1]])) NULL +##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray +#{ .Internal(array(1:4, NULL, NULL)) } +Error: 'dims' cannot be of length 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray +#{ .Internal(array(NA, 1, NULL)) } +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray +#{ .Internal(array(NULL, 1, NULL)) } +Error: 'data' must be of a vector type, was 'NULL' + +##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray +#{ array(1:4, 1:2, 4) } + [,1] [,2] +[1,] 1 2 +Warning message: +In array(1:4, 1:2, 4) : + non-list dimnames are disregarded; will be an error in R 3.3.0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray +#{ 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 +#{ array(1:4, c(1+2i, 2+2i)) } + [,1] [,2] +[1,] 1 2 +Warning message: +In array(1:4, c(1 + (0+2i), 2 + (0+2i))) : + imaginary parts discarded in coercion + +##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray +#{ array(1:4, integer()) } +Error in array(1:4, integer()) : 'dims' cannot be of length 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray +#{ array(NA) } +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray +#{ array(NULL) } +Error in array(NULL) : 'data' must be of a vector type, was 'NULL' + +##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray +#{ array(as.raw(1:4)) } +[1] 01 02 03 04 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray +#{ f<-function() 42; .Internal(array(f, 1, NULL)) } +Error: 'data' must be of a vector type, was 'closure' + ##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testarray1 #argv <- list(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, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L), 59L, structure(list(dr = 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.5')), .Names = 'dr')); .Internal(array(argv[[1]], argv[[2]], argv[[3]])) dr @@ -4902,13 +5133,13 @@ character(0) ##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXct.testasPOSIXct12 #argv <- list(structure(list(sec = 0, min = 2L, hour = 2L, mday = 2L, mon = 1L, year = c(102L, 1102L), wday = 6L, yday = 32L, isdst = -1L), .Names = c('sec', 'min', 'hour', 'mday', 'mon', 'year', 'wday', 'yday', 'isdst'), class = c('POSIXlt', 'POSIXt'), tzone = c('', 'EST', 'EDT')), ''); .Internal(as.POSIXct(argv[[1]], argv[[2]])) -[1] 1012611720 32569520520 +[1] 1012615320 32569524120 ##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXct.testasPOSIXct13 #argv <- list(structure(list(sec = 0, min = 0L, hour = 0L, mday = c(2L, 4L, 6L, 8L, 10L, 12L, 14L, 16L, 18L, 20L, 22L, 24L, 26L, 28L, 30L, 32L), mon = 1L, year = 102L, wday = 6L, yday = 32L, isdst = -1L), .Names = c('sec', 'min', 'hour', 'mday', 'mon', 'year', 'wday', 'yday', 'isdst'), class = c('POSIXlt', 'POSIXt'), tzone = c('', 'EST', 'EDT')), ''); .Internal(as.POSIXct(argv[[1]], argv[[2]])) - [1] 1012604400 1012777200 1012950000 1013122800 1013295600 1013468400 - [7] 1013641200 1013814000 1013986800 1014159600 1014332400 1014505200 -[13] 1014678000 1014850800 1015023600 1015196400 + [1] 1012608000 1012780800 1012953600 1013126400 1013299200 1013472000 + [7] 1013644800 1013817600 1013990400 1014163200 1014336000 1014508800 +[13] 1014681600 1014854400 1015027200 1015200000 ##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXct.testasPOSIXct2 #argv <- list(structure(list(sec = 0, min = 0L, hour = 0L, mday = 1, mon = c(11, 12, 13, 14), year = 100L, wday = 0L, yday = 365L, 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]])) @@ -4916,7 +5147,7 @@ character(0) ##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXct.testasPOSIXct3 #argv <- list(structure(list(sec = 0, min = 0L, hour = 0L, mday = -3L, mon = 1L, year = 102L, wday = 6L, yday = 32L, isdst = -1L), .Names = c('sec', 'min', 'hour', 'mday', 'mon', 'year', 'wday', 'yday', 'isdst'), class = c('POSIXlt', 'POSIXt'), tzone = c('', 'EST', 'EDT')), ''); .Internal(as.POSIXct(argv[[1]], argv[[2]])) -[1] 1012172400 +[1] 1012176000 ##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXct.testasPOSIXct4 #argv <- list(structure(list(sec = 0, min = 0L, hour = 12L, mday = 1L, mon = 0L, year = c(70L, 75L, 80L, 85L, 90L, 95L, 100L, 105L, 110L, 115L), wday = 4L, yday = 0L, 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]])) @@ -4945,7 +5176,7 @@ numeric(0) ##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 04:14:08 CET" "2038-01-19 04:14:08 CET" +[1] "2038-01-19 03:14:08 GMT" "2038-01-19 03:14:08 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt10 #argv <- list(character(0), ''); .Internal(as.POSIXlt(argv[[1]], argv[[2]])) @@ -4957,7 +5188,7 @@ character(0) ##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt2 #argv <- list(structure(c(FALSE, FALSE), class = c('POSIXct', 'POSIXt')), ''); .Internal(as.POSIXlt(argv[[1]], argv[[2]])) -[1] "1970-01-01 01:00:00 CET" "1970-01-01 01:00:00 CET" +[1] "1970-01-01 GMT" "1970-01-01 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt3 #argv <- list(structure(1041324768, class = c('POSIXct', 'POSIXt'), tzone = 'GMT'), 'GMT'); .Internal(as.POSIXlt(argv[[1]], argv[[2]])) @@ -4975,12 +5206,12 @@ character(0) ##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt6 #argv <- list(structure(32569542120, class = c('POSIXct', 'POSIXt')), ''); .Internal(as.POSIXlt(argv[[1]], argv[[2]])) -[1] "3002-02-02 08:02:00 CET" +[1] "3002-02-02 07:02:00 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt7 #argv <- list(structure(c(1012798800, 1013403600, 1014008400, 1014613200), class = c('POSIXct', 'POSIXt'), tzone = ''), ''); .Internal(as.POSIXlt(argv[[1]], argv[[2]])) -[1] "2002-02-04 06:00:00 CET" "2002-02-11 06:00:00 CET" -[3] "2002-02-18 06:00:00 CET" "2002-02-25 06:00:00 CET" +[1] "2002-02-04 05:00:00 GMT" "2002-02-11 05:00:00 GMT" +[3] "2002-02-18 05:00:00 GMT" "2002-02-25 05:00:00 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt8 #argv <- list(structure(c(-1893412800, -1861876800, -1830340800, -1798718400, -1767182400, -1735646400, -1704110400, -1672488000, -1640952000, -1609416000, -1577880000, -1546257600, -1514721600, -1483185600, -1451649600, -1420027200, -1388491200, -1356955200, -1325419200, -1293796800, -1262260800, -1230724800, -1199188800, -1167566400, -1136030400, -1104494400, -1072958400, -1041336000, -1009800000, -978264000, -946728000, -915105600, -883569600, -852033600, -820497600, -788875200, -757339200, -725803200, -694267200, -662644800, -631108800, -599572800, -568036800, -536414400, -504878400, -473342400, -441806400, -410184000, -378648000, -347112000, -315576000, -283953600, -252417600, -220881600, -189345600, -157723200, -126187200, -94651200, -63115200, -31492800, 43200, 31579200, 63115200, 94737600, 126273600, 157809600, 189345600, 220968000, 252504000, 284040000, 315576000, 347198400, 378734400, 410270400, 441806400, 473428800, 504964800, 536500800, 568036800, 599659200, 631195200, 662731200, 694267200, 725889600, 757425600, 788961600, 820497600, 852120000, 883656000, 915192000), class = c('POSIXct', 'POSIXt'), tzone = 'GMT'), 'GMT'); .Internal(as.POSIXlt(argv[[1]], argv[[2]])) @@ -5306,9 +5537,9 @@ Error: unexpected symbol in "ructure('isGrammarSymbol', Rd_tag = 'RCODE')), Rd_t ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascharacter.testascharacter31 #argv <- list(structure(c(1338523200, 1338609600, 1338696000, 1338782400, 1338868800, 1338955200, 1339041600), class = c('POSIXct', 'POSIXt'), tzone = ''));as.character(argv[[1]]); -[1] "2012-06-01 06:00:00" "2012-06-02 06:00:00" "2012-06-03 06:00:00" -[4] "2012-06-04 06:00:00" "2012-06-05 06:00:00" "2012-06-06 06:00:00" -[7] "2012-06-07 06:00:00" +[1] "2012-06-01 04:00:00" "2012-06-02 04:00:00" "2012-06-03 04:00:00" +[4] "2012-06-04 04:00:00" "2012-06-05 04:00:00" "2012-06-06 04:00:00" +[7] "2012-06-07 04:00:00" ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascharacter.testascharacter32 #argv <- list(structure(1:4, class = 'roman'));as.character(argv[[1]]); @@ -5391,7 +5622,7 @@ character(0) ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascharacter.testascharacter5 #argv <- list(structure(1395082040.29392, class = c('POSIXct', 'POSIXt')));as.character(argv[[1]]); -[1] "2014-03-17 19:47:20" +[1] "2014-03-17 18:47:20" ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascharacter.testascharacter6 #argv <- list(structure(2:3, .Label = c('C', 'A', 'B'), class = 'factor'));as.character(argv[[1]]); @@ -5506,6 +5737,20 @@ NAs introduced by coercion #{ as.complex(c(0/0, 0/0)) } [1] NA NA +##com.oracle.truffle.r.test.builtins.TestBuiltin_ascomplex.testAsComplex +#{ as.complex(list("foo")) } +[1] NA +Warning message: +NAs introduced by coercion + +##com.oracle.truffle.r.test.builtins.TestBuiltin_ascomplex.testAsComplex +#{ as.complex(list(42)) } +[1] 42+0i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_ascomplex.testAsComplex +#{ as.complex(list(NULL)) } +Error: (list) object cannot be coerced to type 'complex' + ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascomplex.testAsComplex #{ x<-c(a=1.1, b=2.2); dim(x)<-c(1,2); attr(x, "foo")<-"foo"; y<-as.complex(x); attributes(y) } NULL @@ -5877,8 +6122,9 @@ expression(`123`) expression(1, 2) ##com.oracle.truffle.r.test.builtins.TestBuiltin_asexpression.testAsExpression -#{ as.expression(function()) } -Error: unexpected ')' in "{ as.expression(function())" +#{ as.expression(function() {}) } +Error in as.vector(x, "expression") : + cannot coerce type 'closure' to vector of type 'expression' ##com.oracle.truffle.r.test.builtins.TestBuiltin_asexpression.testAsExpression #{ as.expression(list("x" = 1, "y" = 2)) } @@ -5915,6 +6161,15 @@ 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 +#{ .Internal(as.function.default(alist(a+b), "foo")) } +Error in as.function.default(alist(a + b), "foo") : invalid environment + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asfunction.testasfunction +#{ .Internal(as.function.default(function() 42, parent.frame())) } +Error in as.function.default(function() 42, parent.frame()) : + list argument expected + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asfunction.testasfunction #{ as.function(alist("foo"))() } [1] "foo" @@ -6557,8 +6812,12 @@ In matrix(c(1, 2, 3, 4), 3, 2) : [10,] NA NA NA NA NA NA NA NA NA NA ##com.oracle.truffle.r.test.builtins.TestBuiltin_asmatrix.testMatrix -#{ matrix(c(NaN,4+5i,2+0i,5+10i)} -Error: unexpected '}' in "{ matrix(c(NaN,4+5i,2+0i,5+10i)}" +#{ matrix(c(NaN,4+5i,2+0i,5+10i)) } + [,1] +[1,] NaN+ 0i +[2,] 4+ 5i +[3,] 2+ 0i +[4,] 5+10i ##com.oracle.truffle.r.test.builtins.TestBuiltin_asmatrix.testMatrix #{ matrix(nrow=2,ncol=2) } @@ -6752,6 +7011,16 @@ raw(0) #argv <- list(list());as.raw(argv[[1]]); raw(0) +##com.oracle.truffle.r.test.builtins.TestBuiltin_assign.testassign +#x <- c(1,2,4); e <- new.env(); assign('foo', x, e); x[[1]] <- 5; x; get('foo', e) +[1] 5 2 4 +[1] 1 2 4 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_assign.testassign +#x <- c(1,2,4); e <- new.env(); assign('foo', x, e, inherits=0); x[[1]] <- 5; x; get('foo', e) +[1] 5 2 4 +[1] 1 2 4 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_assign.testassign1 #argv <- structure(list(x = '`', value = TRUE), .Names = c('x', 'value'));do.call('assign', argv) @@ -6773,6 +7042,10 @@ name #{ as.symbol(as.symbol(123)) } `123` +##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector +#as.vector(as.symbol('asdf'), 'symbol') +asdf + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector #as.vector(file('')) [1] 3 @@ -6842,8 +7115,8 @@ Warning messages: Error in as.vector(x, mode) : invalid 'mode' argument ##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector -#{ as.vector(42, c("character", "character") } -Error: unexpected '}' in "{ as.vector(42, c("character", "character") }" +#{ as.vector(42, c("character", "character")) } +Error in as.vector(x, mode) : invalid 'mode' argument ##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector #{ as.vector(42, character()) } @@ -7092,8 +7365,19 @@ $g2 ##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector26 -#argv <- list(quote(list(V1 = c('a', 'd e', 'h'), V2 = c('b'', 'f', 'i'), V3 = c('c', 'g', 'j\nk l m'))), 'list'); .Internal(as.vector(argv[[1]], argv[[2]])) -Error: unexpected string constant in "argv <- list(quote(list(V1 = c('a', 'd e', 'h'), V2 = c('b'', '" +#argv <- list(quote(list(V1 = c('a', 'd e', 'h'), V2 = c('b\'', 'f', 'i'), V3 = c('c', 'g', 'j\nk l m'))), 'list'); .Internal(as.vector(argv[[1]], argv[[2]])) +[[1]] +list + +$V1 +c("a", "d e", "h") + +$V2 +c("b'", "f", "i") + +$V3 +c("c", "g", "j\nk l m") + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector27 #argv <- list(NA, 'integer'); .Internal(as.vector(argv[[1]], argv[[2]])) @@ -7623,6 +7907,56 @@ numeric(0) [1] 0.549306-1.570796i 0.549306-1.570763i -0.549306+1.570796i [4] -0.549306+1.570763i +##com.oracle.truffle.r.test.builtins.TestBuiltin_attach.basicTests +#d <- data.frame(colNameX=c(1,2,3)); attach(d); colNameX +[1] 1 2 3 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_attach.basicTests +#d <- list(col=c(1,2,3)); e <- attach(d, name='hello'); attr(e, 'name') +[1] "hello" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_attach.basicTests +#d <- list(colNameX=c(1,2,3)); attach(d); colNameX +[1] 1 2 3 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_attach.basicTests +#e <- attach(NULL); attr(e, 'name') +[1] "NULL" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_attach.detach +#d <- list(colNameX=c(1,2,3)); attach(d); detach(d); colNameX +Error: object 'colNameX' not found + +##com.oracle.truffle.r.test.builtins.TestBuiltin_attach.sharingTests +#d <- data.frame(colNameX=c(1,2,3)); attach(d); d$colNameX[1] <- 42; colNameX +[1] 1 2 3 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_attach.testArguments +#attach('string') +Error in attach("string") : file 'string' not found + +##com.oracle.truffle.r.test.builtins.TestBuiltin_attach.testArguments +#attach(list(), name=42) +Error in attach(list(), name = 42) : invalid 'name' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_attach.testArguments +#attach(list(x=42), pos='string') +Error in attach(list(x = 42), pos = "string") : 'pos' must be an integer +In addition: Warning message: +In attach(list(x = 42), pos = "string") : NAs introduced by coercion + +##com.oracle.truffle.r.test.builtins.TestBuiltin_attach.testArguments +#detach('string') +Error in detach("string") : invalid 'name' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_attr.testExactMatch +#x <- c(1, 3); attr(x, 'abc') <- 42; attr(x, 'ab', exact=TRUE) +NULL + +##com.oracle.truffle.r.test.builtins.TestBuiltin_attr.testExactMatch +#x <- c(1,2); attr(x, 'row.namess') <- 42; attr(x, 'row.names') +[1] 42 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_attr.testattr1 #argv <- list(structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1), .Dim = c(32L, 23L), .Dimnames = list(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'), c('(Intercept)', 'HairBrown', 'HairRed', 'HairBlond', 'EyeBlue', 'EyeHazel', 'EyeGreen', 'SexFemale', 'HairBrown:EyeBlue', 'HairRed:EyeBlue', 'HairBlond:EyeBlue', 'HairBrown:EyeHazel', 'HairRed:EyeHazel', 'HairBlond:EyeHazel', 'HairBrown:EyeGreen', 'HairRed:EyeGreen', 'HairBlond:EyeGreen', 'HairBrown:SexFemale', 'HairRed:SexFemale', 'HairBlond:SexFemale', 'EyeBlue:SexFemale', 'EyeHazel:SexFemale', 'EyeGreen:SexFemale')), assign = c(0L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 6L, 6L, 6L), contrasts = structure(list(Hair = 'contr.treatment', Eye = 'contr.treatment', Sex = 'contr.treatment'), .Names = c('Hair', 'Eye', 'Sex'))), 'assign');attr(argv[[1]],argv[[2]]); [1] 0 1 1 1 2 2 2 3 4 4 4 4 4 4 4 4 4 5 5 5 6 6 6 @@ -7766,7 +8100,7 @@ character(0) ##com.oracle.truffle.r.test.builtins.TestBuiltin_attr.testattr32 #argv <- list(structure(1:10, date = structure(200171400, class = c('POSIXct', 'POSIXt'), tzone = ''), class = 'stamped'), 'date');attr(argv[[1]],argv[[2]]); -[1] "1976-05-05 20:10:00 CET" +[1] "1976-05-05 19:10:00 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_attr.testattr33 #argv <- list(structure(c(49.9, 52.3, 49.4, 51.1, 49.4, 47.9, 49.8, 50.9, 49.3, 51.9, 50.8, 49.6, 49.3, 50.6, 48.4, 50.7, 50.9, 50.6, 51.5, 52.8, 51.8, 51.1, 49.8, 50.2, 50.4, 51.6, 51.8, 50.9, 48.8, 51.7, 51, 50.6, 51.7, 51.5, 52.1, 51.3, 51, 54, 51.4, 52.7, 53.1, 54.6, 52, 52, 50.9, 52.6, 50.2, 52.6, 51.6, 51.9, 50.5, 50.9, 51.7), .Tsp = c(1, 53, 1)), 'tsp');attr(argv[[1]],argv[[2]]); @@ -7927,6 +8261,14 @@ 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 +#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 +#x<-42; attr(x, NULL) <- NULL +Error in attr(x, NULL) <- NULL : 'name' must be non-null character string + ##com.oracle.truffle.r.test.builtins.TestBuiltin_attrassign.testattrassign1 #argv <- list(structure(1, foo = structure(list(a = 'a'), .Names = 'a')), 'foo', value = structure(list(a = 'a'), .Names = 'a'));`attr<-`(argv[[1]],argv[[2]],argv[[3]]); [1] 1 @@ -8130,7 +8472,7 @@ attr(,"hessian") #argv <- list(structure(c('o', 'p', 'v', 'i', 'r', 'w', 'b', 'm', 'f', 's'), date = structure(1224086400, class = c('POSIXct', 'POSIXt'), tzone = '')), 'date', value = structure(1224086400, class = c('POSIXct', 'POSIXt'), tzone = ''));`attr<-`(argv[[1]],argv[[2]],argv[[3]]); [1] "o" "p" "v" "i" "r" "w" "b" "m" "f" "s" attr(,"date") -[1] "2008-10-15 18:00:00 CEST" +[1] "2008-10-15 16:00:00 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_attrassign.testattrassign7 #argv <- list(structure(list(structure(list(structure(13L, label = 'Illinois', members = 1L, height = 0, leaf = TRUE), structure(32L, label = 'New York', members = 1L, height = 0, leaf = TRUE)), members = 2L, midpoint = 0.5, height = 6.23698645180507), structure(list(structure(22L, label = 'Michigan', members = 1L, height = 0, leaf = TRUE), structure(28L, label = 'Nevada', members = 1L, height = 0, leaf = TRUE)), members = 2L, midpoint = 0.5, height = 13.2973681606549)), members = 4L, midpoint = 1.5, height = 18.4173313943456, class = 'dendrogram', edgePar = structure(list( p.col = 'plum'), .Names = 'p.col'), edgetext = '4 members'), 'edgetext', value = '4 members');`attr<-`(argv[[1]],argv[[2]],argv[[3]]); @@ -8614,7 +8956,7 @@ attr(,"package") ##com.oracle.truffle.r.test.builtins.TestBuiltin_attributes.testattributes5 #argv <- list(structure(c('o', 'p', 'v', 'i', 'r', 'w', 'b', 'm', 'f', 's'), date = structure(1224086400, class = c('POSIXct', 'POSIXt'), tzone = ''), .S3Class = 'stamped', class = structure('stamped', package = '.GlobalEnv')));attributes(argv[[1]]); $date -[1] "2008-10-15 18:00:00 CEST" +[1] "2008-10-15 16:00:00 GMT" $.S3Class [1] "stamped" @@ -8658,6 +9000,13 @@ $extra character(0) +##com.oracle.truffle.r.test.builtins.TestBuiltin_attributesassign.testArgsCasts +#x <- 42; attributes(x) <- 44 +Error in attributes(x) <- 44 : attributes must be a list or NULL + +##com.oracle.truffle.r.test.builtins.TestBuiltin_attributesassign.testArgsCasts +#x <- 42; attributes(x) <- NULL + ##com.oracle.truffle.r.test.builtins.TestBuiltin_attributesassign.testattributesassign1 #argv <- list(NULL, NULL);`attributes<-`(argv[[1]],argv[[2]]); NULL @@ -9195,6 +9544,10 @@ Warning message: In bitwShiftL(c(3, 2, 4), c(3 + (0+3i))) : imaginary parts discarded in coercion +##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions +#{ bitwShiftL(c(8,4,2), NULL) } +integer(0) + ##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions #{ bitwShiftR(c(1,2,3,4), c("Hello")) } [1] NA NA NA NA @@ -9862,12 +10215,22 @@ x y 1 2 ##com.oracle.truffle.r.test.builtins.TestBuiltin_c.testCombine -#{ e1 <- new.env(), c(e1, 3) } -Error: unexpected ',' in "{ e1 <- new.env()," +#{ e1 <- new.env(); c(e1, 3) } +[[1]] +<environment: 0x7fcda18374e8> + +[[2]] +[1] 3 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_c.testCombine -#{ e1 <- new.env(), e2 <- new.env(); c(e1, e2) } -Error: unexpected ',' in "{ e1 <- new.env()," +#{ e1 <- new.env(); e2 <- new.env(); c(e1, e2) } +[[1]] +<environment: 0x7fabc59615f0> + +[[2]] +<environment: 0x7fabc5961200> + ##com.oracle.truffle.r.test.builtins.TestBuiltin_c.testCombine #{ f <- function() { }; length(c(f, 2)) == 2 } @@ -10030,7 +10393,7 @@ $Residuals ##com.oracle.truffle.r.test.builtins.TestBuiltin_c.testc13 #argv <- list(structure(1208822400, class = c('POSIXct', 'POSIXt')), structure(1209168000, class = c('POSIXct', 'POSIXt')));c(argv[[1]],argv[[2]]); -[1] "2008-04-22 02:00:00 CEST" "2008-04-26 02:00:00 CEST" +[1] "2008-04-22 GMT" "2008-04-26 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_c.testc14 #argv <- list(`Grand mean` = structure(103.87323943662, class = 'mtable'), structure(list(N = structure(c(78.7365206866197, 98.5088731171753, 113.842206450509, 123.008873117175), .Dim = 4L, .Dimnames = structure(list(N = c('0.0cwt', '0.2cwt', '0.4cwt', '0.6cwt')), .Names = 'N'), class = 'mtable'), `V:N` = structure(c(79.5323303457107, 86.1989970123773, 69.7732394366197, 98.0323303457106, 108.032330345711, 89.1989970123773, 114.198997012377, 116.698997012377, 110.365663679044, 124.365663679044, 126.365663679044, 118.032330345711), .Dim = 3:4, .Dimnames = structure(list(V = c('Golden.rain', 'Marvellous', 'Victory'), N = c('0.0cwt', '0.2cwt', '0.4cwt', '0.6cwt')), .Names = c('V', 'N')), class = 'mtable')), .Names = c('N', 'V:N')));c(argv[[1]],argv[[2]]); @@ -10726,7 +11089,7 @@ list() ##com.oracle.truffle.r.test.builtins.TestBuiltin_c.testc64 #argv <- list(structure(1386393974.25184, class = c('POSIXct', 'POSIXt')), structure(1386393974.25184, class = c('POSIXct', 'POSIXt')));c(argv[[1]],argv[[2]]); -[1] "2013-12-07 06:26:14 CET" "2013-12-07 06:26:14 CET" +[1] "2013-12-07 05:26:14 GMT" "2013-12-07 05:26:14 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_c.testc65 #argv <- list('BiocInstaller', '/home/lzhao/R/x86_64-unknown-linux-gnu-library/3.0', structure(c('1.12.0', NA, 'R (>= 3.0.0)', NA, NA, 'RUnit, BiocGenerics', NA, 'Artistic-2.0', NA, NA, NA, NA, NA, NA, '3.0.1'), .Names = c('Version', NA, 'Depends', NA, NA, 'Suggests', NA, 'License', NA, NA, NA, NA, NA, NA, 'Built')));c(argv[[1]],argv[[2]],argv[[3]]); @@ -10848,7 +11211,7 @@ $x.limits [1] -2.464082 2.925125 $y.limits -[1] "2013-12-08 06:11:30 CET" "2013-12-21 07:41:30 CET" +[1] "2013-12-08 05:11:30 GMT" "2013-12-21 06:41:30 GMT" $x.used.at NULL @@ -12097,6 +12460,16 @@ Error in chol.default(m) : [4,] 0.000000 0.000000 0.0000000 1.1547005 -0.5773503 [5,] 0.000000 0.000000 0.0000000 0.0000000 1.0000000 +##com.oracle.truffle.r.test.builtins.TestBuiltin_choose.testWithNonNumericArgs +#.Internal(choose('hello', 3)) +Error in choose("hello", 3) : + non-numeric argument to mathematical function + +##com.oracle.truffle.r.test.builtins.TestBuiltin_choose.testWithNonNumericArgs +#.Internal(choose(3, 'hello')) +Error in choose(3, "hello") : + non-numeric argument to mathematical function + ##com.oracle.truffle.r.test.builtins.TestBuiltin_choose.testchoose1 #.Internal(choose(-1, 3)) [1] -1 @@ -12490,7 +12863,7 @@ attr(,"class")attr(,"package") #argv <- list(structure(c('o', 'p', 'v', 'i', 'r', 'w', 'b', 'm', 'f', 's'), date = structure(1224086400, class = c('POSIXct', 'POSIXt'), tzone = ''), class = 'stamped'), value = 'stamped');`class<-`(argv[[1]],argv[[2]]); [1] "o" "p" "v" "i" "r" "w" "b" "m" "f" "s" attr(,"date") -[1] "2008-10-15 18:00:00 CEST" +[1] "2008-10-15 16:00:00 GMT" attr(,"class") [1] "stamped" @@ -13525,7 +13898,7 @@ attr(,"row.names") attr(,".S3Class") [1] "data.frame" attr(,"timestamps") -[1] "2013-12-07 05:53:53 CET" +[1] "2013-12-07 04:53:53 GMT" attr(,"class") [1] "myFrame" attr(,"class")attr(,"package") @@ -15085,7 +15458,7 @@ character(0) ##com.oracle.truffle.r.test.builtins.TestBuiltin_date.testDate #{date()} -[1] "Sat Mar 12 03:17:13 2016" +[1] "Thu Sep 8 05:44:20 2016" ##com.oracle.truffle.r.test.builtins.TestBuiltin_delayedAssign.testDelayedAssign #{ delayedAssign("x", a+b); a <- 1 ; b <- 3 ; x } @@ -17405,6 +17778,12 @@ NULL [1] "JJ" "sm[, 1]" "sm[, 3] - 0.5" +##com.oracle.truffle.r.test.builtins.TestBuiltin_dimnamesassign.testDimnamesAssign +#{ x<-data.frame(c(1,2),c(3,4)); dimnames(x) <- list(c("A", "B"), c("C", "D")); x } + C D +A 1 3 +B 2 4 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_dimnamesassign.testdimnamesassign1 #argv <- list(structure(c(300, 3000, 400, 4000), .Dim = c(2L, 2L, 1L), .Dimnames = list(c('happy', 'sad'), NULL, '')), value = list(c('happy', 'sad'), NULL, ''));`dimnames<-`(argv[[1]],argv[[2]]); , , @@ -18069,6 +18448,11 @@ logical(0) #{ duplicated(c(1,2,1)) } [1] FALSE FALSE TRUE +##com.oracle.truffle.r.test.builtins.TestBuiltin_duplicated.testDuplicated +#{ duplicated(c(1,2,1), incomparables=function() 42) } +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 #{ duplicated(c(1,2,3,2), incomparables = c(2+6i)) } [1] FALSE FALSE FALSE FALSE @@ -18115,6 +18499,14 @@ In duplicated.default(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = "cat") : #{ duplicated(list(76.5, 5L, 5L, 76.5, 5, 5), incomparables = c(5L, 76.5)) } [1] FALSE FALSE TRUE FALSE FALSE FALSE +##com.oracle.truffle.r.test.builtins.TestBuiltin_duplicated.testDuplicated +#{ x<-function() 42; duplicated(x) } +Error in duplicated.default(x) : duplicated() applies only to vectors + +##com.oracle.truffle.r.test.builtins.TestBuiltin_duplicated.testDuplicated +#{ x<-quote(f(7, 42)); duplicated(x) } +Error in duplicated.default(x) : duplicated() applies only to vectors + ##com.oracle.truffle.r.test.builtins.TestBuiltin_duplicated.testDuplicated #{duplicated(c("abc"))} [1] FALSE @@ -18217,6 +18609,10 @@ logical(0) #argv <- list(structure('lattice', .Names = ''), FALSE, FALSE, NA); .Internal(duplicated(argv[[1]], argv[[2]], argv[[3]], argv[[4]])) [1] FALSE +##com.oracle.truffle.r.test.builtins.TestBuiltin_enc2native.testInvalidArguments +#enc2native(42); +Error in enc2native(42) : argumemt is not a character vector + ##com.oracle.truffle.r.test.builtins.TestBuiltin_enc2native.testenc2native1 #argv <- list(character(0));enc2native(argv[[1]]); character(0) @@ -18229,6 +18625,10 @@ named character(0) #argv <- list('José Pinheiro [aut] (S version)');enc2native(argv[[1]]); [1] "José Pinheiro [aut] (S version)" +##com.oracle.truffle.r.test.builtins.TestBuiltin_enc2utf8.testInvalidArguments +#enc2utf8(42); +Error in enc2utf8(42) : argumemt is not a character vector + ##com.oracle.truffle.r.test.builtins.TestBuiltin_enc2utf8.testenc2utf81 #argv <- list('Add Text to a Plot');enc2utf8(argv[[1]]); [1] "Add Text to a Plot" @@ -18416,6 +18816,16 @@ NULL #argv <- list(structure(numeric(0), .Dim = c(0L, 0L))); .Internal(environmentName(argv[[1]])) [1] "" +##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1 +#{ e1 <- 1; e2 <- new.env(); environment(e1) <- e2 } + +##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1 +#{ e1 <- 1; environment(e1) <- 3 } +Error in environment(e1) <- 3 : replacement object is not an environment + +##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1 +#{ e1 <- 1; environment(e1) <- NULL } + ##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1 #{ e1 <- new.env(); e2 <- new.env(); environment(e1) <- e2 } @@ -18426,6 +18836,11 @@ Error in environment(e1) <- 3 : replacement object is not an environment ##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1 #{ e1 <- new.env(); environment(e1) <- NULL } +##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1 +#{ f <- NULL; environment(f) <- new.env() } +Error in environment(f) <- new.env() : + attempt to set an attribute on NULL + ##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 @@ -18433,6 +18848,22 @@ Error in environment(e1) <- 3 : replacement object is not an environment ##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1 #{ f <- function() {}; e1 <- new.env(); environment(f) <- e1 } +##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1 +#{ f <- function() {}; environment(f) <- NULL } +Error in environment(f) <- NULL : use of NULL environment is defunct + +##com.oracle.truffle.r.test.builtins.TestBuiltin_eval.testEval +#eval('foo') +[1] "foo" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_eval.testEval +#eval(as.symbol('baseenv')) +function () .Primitive("baseenv") + +##com.oracle.truffle.r.test.builtins.TestBuiltin_eval.testEval +#eval(as.symbol('foo')) +Error in eval(expr, envir, enclos) : object 'foo' not found + ##com.oracle.truffle.r.test.builtins.TestBuiltin_eval.testEval #eval({ xx <- pi; xx^2}) ; xx [1] 9.869604 @@ -18535,6 +18966,22 @@ Error in eval(expr, envir, enclos) : object 'a' not found #argv <- structure(list(x = '.Device'), .Names = 'x');do.call('exists', argv) [1] TRUE +##com.oracle.truffle.r.test.builtins.TestBuiltin_exists.testexists1 +#exists('.Device', inherit=FALSE) +[1] FALSE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_exists.testexists1 +#exists('somethingthatdoesnotexist123456789') +[1] FALSE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_exists.testexists1 +#x <- '42'; exists('x', mode='numeric') +[1] FALSE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_exists.testexists1 +#x <- 42; exists('x', mode='numeric') +[1] TRUE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_exp.testExp #{ round( exp(1+2i), digits=5 ) } [1] -1.1312+2.47173i @@ -19100,201 +19547,6 @@ func(a = "a", b = "b") [196] f b d c c Levels: a b c d e f -##com.oracle.truffle.r.test.builtins.TestBuiltin_extract_parentasis_dataframe.testextract_parentasis_dataframe1 -#argv <- structure(list(x = structure(list(ID = c(13, 41, 121, 202, 247, 292, 415, 492), Location = c(0.15998329123474, 0.533277637449134, 1.5998329123474, 2.6797201281819, 3.27965747031217, 3.87959481244245, 5.51942354759854, 6.54598299968812), Peak_Value = c(0.997547264684804, 0.949162789397664, 0.990440013891923, 0.973478735915337, 0.93861267739627, 0.957347289323235, 0.924803043529451, 0.968307855031101)), .Names = c('ID', 'Location', 'Peak_Value'), row.names = c(NA, -8L), class = 'data.frame'), i = 2), .Names = c('x', 'i'));do.call('[.data.frame', argv) - Location -1 0.1599833 -2 0.5332776 -3 1.5998329 -4 2.6797201 -5 3.2796575 -6 3.8795948 -7 5.5194235 -8 6.5459830 -Warning message: -In `[.data.frame`(x = list(ID = c(13, 41, 121, 202, 247, 292, 415, : - named arguments other than 'drop' are discouraged - -##com.oracle.truffle.r.test.builtins.TestBuiltin_extract_parentasis_dataframe.testextract_parentasis_dataframe2 -#argv <- structure(list(x = structure(list(Satellites = c(8L, 0L, 9L, 0L, 4L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 11L, 0L, 14L, 8L, 1L, 1L, 0L, 5L, 4L, 3L, 1L, 2L, 3L, 0L, 3L, 5L, 0L, 0L, 4L, 0L, 0L, 8L, 5L, 0L, 0L, 6L, 0L, 6L, 3L, 5L, 6L, 5L, 9L, 4L, 6L, 4L, 3L, 3L, 5L, 5L, 6L, 4L, 5L, 15L, 3L, 3L, 0L, 0L, 0L, 5L, 3L, 5L, 1L, 8L, 10L, 0L, 0L, 3L, 7L, 1L, 0L, 6L, 0L, 0L, 3L, 4L, 0L, 5L, 0L, 0L, 0L, 4L, 0L, 3L, 0L, 0L, 0L, 0L, 5L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 4L, 1L, 1L, 1L, 1L, 2L, 4L, 3L, 6L, 0L, 2L, 2L, 0L, 12L, 0L, 5L, 6L, 6L, 2L, 0L, 2L, 3L, 0L, 3L, 4L, 2L, 6L, 6L, 0L, 4L, 10L, 7L, 0L, 5L, 5L, 6L, 6L, 7L, 3L, 3L, 0L, 0L, 8L, 4L, 4L, 10L, 9L, 4L, 0L, 0L, 0L, 0L, 4L, 0L, 2L, 0L, 4L, 4L, 3L, 8L, 0L, 7L, 0L, 0L, 2L, 3L, 4L, 0L, 0L, 0L), Width = c(28.3, 22.5, 26, 24.8, 26, 23.8, 26.5, 24.7, 23.7, 25.6, 24.3, 25.8, 28.2, 21, 26, 27.1, 25.2, 29, 24.7, 27.4, 23.2, 25, 22.5, 26.7, 25.8, 26.2, 28.7, 26.8, 27.5, 24.9, 29.3, 25.8, 25.7, 25.7, 26.7, 23.7, 26.8, 27.5, 23.4, 27.9, 27.5, 26.1, 27.7, 30, 28.5, 28.9, 28.2, 25, 28.5, 30.3, 24.7, 27.7, 27.4, 22.9, 25.7, 28.3, 27.2, 26.2, 27.8, 25.5, 27.1, 24.5, 27, 26, 28, 30, 29, 26.2, 26.5, 26.2, 25.6, 23, 23, 25.4, 24.2, 22.9, 26, 25.4, 25.7, 25.1, 24.5, 27.5, 23.1, 25.9, 25.8, 27, 28.5, 25.5, 23.5, 24, 29.7, 26.8, 26.7, 28.7, 23.1, 29, 25.5, 26.5, 24.5, 28.5, 28.2, 24.5, 27.5, 24.7, 25.2, 27.3, 26.3, 29, 25.3, 26.5, 27.8, 27, 25.7, 25, 31.9, 23.7, 29.3, 22, 25, 27, 23.8, 30.2, 26.2, 24.2, 27.4, 25.4, 28.4, 22.5, 26.2, 24.9, 24.5, 25.1, 28, 25.8, 27.9, 24.9, 28.4, 27.2, 25, 27.5, 33.5, 30.5, 29, 24.3, 25.8, 25, 31.7, 29.5, 24, 30, 27.6, 26.2, 23.1, 22.9, 24.5, 24.7, 28.3, 23.9, 23.8, 29.8, 26.5, 26, 28.2, 25.7, 26.5, 25.8, 24.1, 26.2, 26.1, 29, 28, 27, 24.5), Dark = structure(c(1L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 1L), .Label = c('no', 'yes'), class = 'factor'), GoodSpine = structure(c(1L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L), .Label = c('no', 'yes'), class = 'factor'), Rep1 = c(2, 4, 5, 6, 6, 8, 9, 9, 10, 10, 11, 11, 13, 15, 15, 15, 15, 15, 17, 18, 19, 19, 19, 20, 20, 21, 21, 22, 23, 25, 25, 26, 27, 27, 28, 29, 29, 31, 33, 33, 36, 39, 40, 40, 41, 42, 43, 44, 45, 45, 49, 50, 51, 53, 55, 55, 56, 56, 56, 58, 59, 59, 60, 60, 62, 63, 64, 64, 64, 65, 66, 66, 67, 68, 70, 70, 71, 74, 75, 76, 76, 77, 79, 79, 79, 80, 80, 81, 82, 83, 83, 84, 87, 88, 88, 91, 92, 95, 97, 97, 97, 98, 98, 99, 100, 100, 101, 101, 103, 103, 103, 106, 107, 107, 111, 112, 112, 113, 113, 116, 116, 117, 117, 120, 122, 122, 122, 124, 125, 126, 127, 128, 128, 129, 130, 131, 133, 134, 134, 135, 141, 144, 146, 147, 147, 153, 153, 154, 154, 155, 155, 155, 156, 157, 157, 161, 163, 163, 164, 164, 164, 165, 167, 168, 168, 169, 170, 170, 170, 171, 171, 173, 173), Rep2 = c(2, 5, 6, 6, 8, 8, 9, 11, 12, 13, 13, 15, 15, 15, 16, 17, 17, 18, 19, 20, 23, 24, 24, 24, 25, 25, 26, 26, 27, 28, 29, 30, 30, 32, 33, 34, 38, 39, 39, 41, 42, 47, 48, 49, 49, 51, 54, 55, 55, 56, 57, 59, 59, 62, 63, 65, 67, 68, 69, 69, 70, 73, 75, 76, 76, 77, 78, 79, 81, 82, 83, 84, 85, 85, 85, 86, 87, 88, 89, 91, 92, 92, 92, 92, 96, 98, 98, 99, 100, 101, 101, 102, 103, 104, 104, 104, 105, 107, 107, 107, 108, 109, 109, 110, 111, 111, 111, 112, 112, 112, 113, 113, 115, 116, 117, 120, 122, 123, 123, 124, 124, 125, 125, 126, 128, 130, 131, 131, 131, 131, 132, 133, 133, 134, 134, 136, 137, 138, 139, 139, 141, 143, 144, 144, 145, 145, 150, 150, 150, 152, 152, 153, 154, 155, 155, 156, 157, 157, 158, 159, 160, 161, 163, 163, 166, 167, 169, 170, 172, 173, 173, 173, 173)), .Names = c('Satellites', 'Width', 'Dark', 'GoodSpine', 'Rep1', 'Rep2'), row.names = c(NA, -173L), class = 'data.frame'), i = c(2, 4, 5, 6, 6, 8, 9, 9, 10, 10, 11, 11, 13, 15, 15, 15, 15, 15, 17, 18, 19, 19, 19, 20, 20, 21, 21, 22, 23, 25, 25, 26, 27, 27, 28, 29, 29, 31, 33, 33, 36, 39, 40, 40, 41, 42, 43, 44, 45, 45, 49, 50, 51, 53, 55, 55, 56, 56, 56, 58, 59, 59, 60, 60, 62, 63, 64, 64, 64, 65, 66, 66, 67, 68, 70, 70, 71, 74, 75, 76, 76, 77, 79, 79, 79, 80, 80, 81, 82, 83, 83, 84, 87, 88, 88, 91, 92, 95, 97, 97, 97, 98, 98, 99, 100, 100, 101, 101, 103, 103, 103, 106, 107, 107, 111, 112, 112, 113, 113, 116, 116, 117, 117, 120, 122, 122, 122, 124, 125, 126, 127, 128, 128, 129, 130, 131, 133, 134, 134, 135, 141, 144, 146, 147, 147, 153, 153, 154, 154, 155, 155, 155, 156, 157, 157, 161, 163, 163, 164, 164, 164, 165, 167, 168, 168, 169, 170, 170, 170, 171, 171, 173, 173), j = c(-5L, -6L)), .Names = c('x', 'i', 'j'));do.call('[.data.frame', argv) - Satellites Width Dark GoodSpine -2 0 22.5 yes no -4 0 24.8 yes no -5 4 26.0 yes no -6 0 23.8 no no -6.1 0 23.8 no no -8 0 24.7 yes yes -9 0 23.7 no yes -9.1 0 23.7 no yes -10 0 25.6 yes no -10.1 0 25.6 yes no -11 0 24.3 yes no -11.1 0 24.3 yes no -13 11 28.2 no no -15 14 26.0 no yes -15.1 14 26.0 no yes -15.2 14 26.0 no yes -15.3 14 26.0 no yes -15.4 14 26.0 no yes -17 1 25.2 no no -18 1 29.0 no no -19 0 24.7 yes no -19.1 0 24.7 yes no -19.2 0 24.7 yes no -20 5 27.4 no no -20.1 5 27.4 no no -21 4 23.2 no yes -21.1 4 23.2 no yes -22 3 25.0 no yes -23 1 22.5 no yes -25 3 25.8 yes no -25.1 3 25.8 yes no -26 0 26.2 yes no -27 3 28.7 no no -27.1 3 28.7 no no -28 5 26.8 no yes -29 0 27.5 yes no -29.1 0 27.5 yes no -31 4 29.3 no yes -33 0 25.7 no yes -33.1 0 25.7 no yes -36 0 23.7 yes no -39 0 23.4 yes no -40 6 27.9 no no -40.1 6 27.9 no no -41 3 27.5 yes no -42 5 26.1 no yes -43 6 27.7 no yes -44 5 30.0 no yes -45 9 28.5 yes yes -45.1 9 28.5 yes yes -49 3 28.5 no no -50 3 30.3 no yes -51 5 24.7 yes no -53 6 27.4 no yes -55 5 25.7 no yes -55.1 5 25.7 no yes -56 15 28.3 no no -56.1 15 28.3 no no -56.2 15 28.3 no no -58 3 26.2 yes no -59 0 27.8 no yes -59.1 0 27.8 no yes -60 0 25.5 yes no -60.1 0 25.5 yes no -62 5 24.5 yes no -63 3 27.0 yes yes -64 5 26.0 no no -64.1 5 26.0 no no -64.2 5 26.0 no no -65 1 28.0 no no -66 8 30.0 no no -66.1 8 30.0 no no -67 10 29.0 no no -68 0 26.2 no no -70 3 26.2 no no -70.1 3 26.2 no no -71 7 25.6 yes no -74 6 25.4 no no -75 0 24.2 yes no -76 0 22.9 no yes -76.1 0 22.9 no yes -77 3 26.0 yes yes -79 0 25.7 yes no -79.1 0 25.7 yes no -79.2 0 25.7 yes no -80 5 25.1 no no -80.1 5 25.1 no no -81 0 24.5 yes yes -82 0 27.5 yes no -83 0 23.1 yes no -83.1 0 23.1 yes no -84 4 25.9 yes yes -87 0 28.5 no no -88 0 25.5 yes yes -88.1 0 25.5 yes yes -91 5 29.7 no yes -92 0 26.8 no yes -95 0 23.1 yes no -97 0 25.5 yes no -97.1 0 25.5 yes no -97.2 0 25.5 yes no -98 1 26.5 yes no -98.1 1 26.5 yes no -99 1 24.5 yes no -100 1 28.5 yes no -100.1 1 28.5 yes no -101 1 28.2 no no -101.1 1 28.2 no no -103 1 27.5 no no -103.1 1 27.5 no no -103.2 1 27.5 no no -106 1 27.3 yes no -107 1 26.3 no no -107.1 1 26.3 no no -111 3 27.8 no no -112 6 27.0 no no -112.1 6 27.0 no no -113 0 25.7 yes no -113.1 0 25.7 yes no -116 0 23.7 yes no -116.1 0 23.7 yes no -117 12 29.3 yes no -117.1 12 29.3 yes no -120 6 27.0 yes no -122 2 30.2 no yes -122.1 2 30.2 no yes -122.2 2 30.2 no yes -124 2 24.2 no no -125 3 27.4 no no -126 0 25.4 no yes -127 3 28.4 yes no -128 4 22.5 yes no -128.1 4 22.5 yes no -129 2 26.2 no no -130 6 24.9 no yes -131 6 24.5 no yes -133 4 28.0 no yes -134 10 25.8 yes no -134.1 10 25.8 yes no -135 7 27.9 no no -141 7 33.5 no yes -144 0 24.3 no yes -146 8 25.0 yes no -147 4 31.7 no yes -147.1 4 31.7 no yes -153 0 23.1 no yes -153.1 0 23.1 no yes -154 0 22.9 no yes -154.1 0 22.9 no yes -155 0 24.5 yes no -155.1 0 24.5 yes no -155.2 0 24.5 yes no -156 4 24.7 no no -157 0 28.3 no no -157.1 0 28.3 no no -161 4 26.5 no no -163 8 28.2 no no -163.1 8 28.2 no no -164 0 25.7 yes no -164.1 0 25.7 yes no -164.2 0 25.7 yes no -165 7 26.5 no no -167 0 24.1 yes no -168 2 26.2 yes no -168.1 2 26.2 yes no -169 3 26.1 yes no -170 4 29.0 yes no -170.1 4 29.0 yes no -170.2 4 29.0 yes no -171 0 28.0 no yes -171.1 0 28.0 no yes -173 0 24.5 no yes -173.1 0 24.5 no yes -Warning message: -In `[.data.frame`(x = list(Satellites = c(8L, 0L, 9L, 0L, 4L, 0L, : - named arguments other than 'drop' are discouraged - ##com.oracle.truffle.r.test.builtins.TestBuiltin_extract_parentasis_extract_parentasis_assign_factor.testextract_parentasis_extract_parentasis_assign_factor1 #argv <- structure(list(x = structure(c(2L, 2L, 3L), .Label = c('One', 'Two', 'Three'), class = 'factor'), 2, value = 'One'), .Names = c('x', '', 'value'));do.call('[[<-.factor', argv) [1] Two One Three @@ -20606,6 +20858,44 @@ attr(,"useBytes") [1] TRUE +##com.oracle.truffle.r.test.builtins.TestBuiltin_gregexpr.testRegExpr +#{ .Internal(gregexpr("7", 42, F, F, F, F)) } +Error: invalid 'text' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_gregexpr.testRegExpr +#{ .Internal(gregexpr(7, "42", F, F, F, F)) } +Error: invalid 'pattern' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_gregexpr.testRegExpr +#{ .Internal(gregexpr(character(), "42", F, F, F, F)) } +Error: invalid 'pattern' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_gregexpr.testRegExpr +#{ x<-gregexpr("foo", c("bar foo foo", "foo"), fixed=F); as.integer(c(x[[1]], x[[2]])) } +[1] 5 9 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_gregexpr.testRegExpr +#{ x<-gregexpr("foo", c("bar foo foo", "foo"), fixed=F); list(attr(x[[1]], "match.length"), attr(x[[2]], "match.length")) } +[[1]] +[1] 3 3 + +[[2]] +[1] 3 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_gregexpr.testRegExpr +#{ x<-gregexpr("foo", c("bar foo foo", "foo"), fixed=T); as.integer(c(x[[1]], x[[2]])) } +[1] 5 9 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_gregexpr.testRegExpr +#{ x<-gregexpr("foo", c("bar foo foo", "foo"), fixed=T); list(attr(x[[1]], "match.length"), attr(x[[2]], "match.length")) } +[[1]] +[1] 3 3 + +[[2]] +[1] 3 + + ##com.oracle.truffle.r.test.builtins.TestBuiltin_gregexpr.testgregexpr1 #argv <- list('', 'abc', FALSE, FALSE, FALSE, FALSE); .Internal(gregexpr(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]])) [[1]] @@ -20775,6 +21065,18 @@ attr(,"useBytes") [1] TRUE +##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep +#{ .Internal(grep("7", 7, F, F, F, F, F, F)) } +Error: invalid 'text' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep +#{ .Internal(grep(7, "7", F, F, F, F, F, F)) } +Error: invalid 'pattern' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep +#{ .Internal(grep(character(), "7", F, F, F, F, F, F)) } +Error: invalid 'pattern' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep #{ txt<-c("1+1i", "7", "42.1", "7+42i"); grep("[0-9].*[-+][0-9].*i$", txt) } [1] 1 4 @@ -20863,7 +21165,19 @@ integer(0) #argv <- list('^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789]', 'all.R', FALSE, FALSE, FALSE, FALSE, 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_grepl.testGrep +##com.oracle.truffle.r.test.builtins.TestBuiltin_grepl.testGrepl +#{ .Internal(grepl("7", 7, F, F, F, F, F, F)) } +Error: invalid 'text' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_grepl.testGrepl +#{ .Internal(grepl(7, "7", F, F, F, F, F, F)) } +Error: invalid 'pattern' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_grepl.testGrepl +#{ .Internal(grepl(character(), "7", F, F, F, F, F, F)) } +Error: invalid 'pattern' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_grepl.testGrepl #{ txt<-c("arm","foot","lefroo", "bafoobar"); grepl("foo", txt) } [1] FALSE TRUE FALSE TRUE @@ -20930,42 +21244,62 @@ list() NULL -##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testSub +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub +#{ .Internal(gsub("7", "42", 7, F, F, F, F)) } +Error: invalid 'text' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub +#{ .Internal(gsub("7", 42, "7", F, F, F, F)) } +Error: invalid 'replacement' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub +#{ .Internal(gsub("7", character(), "7", F, F, F, F)) } +Error: invalid 'replacement' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub +#{ .Internal(gsub(7, "42", "7", F, F, F, F)) } +Error: invalid 'pattern' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub +#{ .Internal(gsub(character(), "42", "7", F, F, F, F)) } +Error: invalid 'pattern' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub #{ gsub("([a-e])","\\1\\1", "prague alley") } [1] "praaguee aalleey" -##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testSub +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub #{ gsub("a","aa", "prAgue alley") } [1] "prAgue aalley" -##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testSub +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub #{ gsub("a","aa", "prAgue alley", fixed=TRUE) } [1] "prAgue aalley" -##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testSub +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub #{ gsub("a","aa", "prAgue alley", fixed=TRUE, ignore.case=TRUE) } [1] "prAgue aalley" Warning message: In gsub("a", "aa", "prAgue alley", fixed = TRUE, ignore.case = TRUE) : argument 'ignore.case = TRUE' will be ignored -##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testSub +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub #{ gsub("a","aa", "prAgue alley", ignore.case=TRUE) } [1] "praague aalley" -##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testSub +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub #{ gsub("a","aa", "prague alley") } [1] "praague aalley" -##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testSub +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub #{ gsub("a","aa", "prague alley", fixed=TRUE) } [1] "praague aalley" -##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testSub +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub #{ gsub("h","", c("hello", "hi", "bye")) } [1] "ello" "i" "bye" -##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testSub +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub #{ gsub("h","", c("hello", "hi", "bye"), fixed=TRUE) } [1] "ello" "i" "bye" @@ -21125,6 +21459,34 @@ Error: unexpected '[' in "argv <- list(''([" attr(,"Rd_tag") [1] "TEXT" +##com.oracle.truffle.r.test.builtins.TestBuiltin_iconv.testIconv +#{ .Internal(iconv("7", "latin1", "ASCII", 42, T, F)) } +Error: invalid 'sub' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_iconv.testIconv +#{ .Internal(iconv("7", "latin1", "ASCII", character(), T, F)) } +Error: invalid 'sub' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_iconv.testIconv +#{ .Internal(iconv("7", "latin1", c("ASCII", "ASCII"), "42", T, F)) } +Error: invalid 'to' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_iconv.testIconv +#{ .Internal(iconv("7", "latin1", character(), "42", T, F)) } +Error: invalid 'to' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_iconv.testIconv +#{ .Internal(iconv("7", c("latin1", "latin1"), "ASCII", "42", T, F)) } +Error: invalid 'from' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_iconv.testIconv +#{ .Internal(iconv("7", character(), "ASCII", "42", T, F)) } +Error: invalid 'from' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_iconv.testIconv +#{ .Internal(iconv(7, "latin1", "ASCII", "42", T, F)) } +Error: 'x' must be a character vector + ##com.oracle.truffle.r.test.builtins.TestBuiltin_iconv.testiconv1 #argv <- list('Report Information on C Stack Size and Usage', 'UTF-8', '', 'byte', FALSE, FALSE); .Internal(iconv(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]])) [1] "Report Information on C Stack Size and Usage" @@ -21572,6 +21934,10 @@ attr(,"Rd_tag") #argv <- structure(list(test = c(TRUE, TRUE, FALSE, TRUE, FALSE), yes = 'True', no = 'False'), .Names = c('test', 'yes', 'no'));do.call('ifelse', argv) [1] "True" "True" "False" "True" "False" +##com.oracle.truffle.r.test.builtins.TestBuiltin_inherits.testInherits +#inherits(NULL, 'NULL') +[1] TRUE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_inherits.testInherits #{ e <- new.env(); class(e)<-"abc"; inherits(e, "abc") } [1] TRUE @@ -23914,8 +24280,10 @@ FALSE FALSE [5,] FALSE TRUE ##com.oracle.truffle.r.test.builtins.TestBuiltin_isna.testIsNA -#is.na(is.na)) -Error: unexpected ')' in "is.na(is.na))" +#is.na(is.na) +[1] 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 #is.na(quote(x())) @@ -24776,6 +25144,18 @@ Error: unexpected symbol in "0.2, 18, 20, 20, 22.7, 16.3, 18.7, 21, 24.5, 17.8, #argv <- list(structure(3.14159265358979, class = structure('3.14159265358979', class = 'testit')));is.symbol(argv[[1]]); [1] FALSE +##com.oracle.truffle.r.test.builtins.TestBuiltin_isunsorted.testIsUnsorted +#{ is.unsorted(c(1+1i,2+1i,2+1i), strictly=FALSE) } +[1] FALSE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_isunsorted.testIsUnsorted +#{ is.unsorted(c(1+1i,2+1i,2+1i), strictly=TRUE) } +[1] TRUE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_isunsorted.testIsUnsorted +#{ is.unsorted(c(1,2,2,3), strictly=TRUE) } +[1] TRUE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_isunsorted.testIsUnsorted #{ is.unsorted(c(1,2,3,4)) } [1] FALSE @@ -24883,6 +25263,14 @@ Error: unexpected symbol in "0.2, 18, 20, 20, 22.7, 16.3, 18.7, 21, 24.5, 17.8, ##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector #{ x<-list(1,3); } +##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector +#{is.vector(c(1,2), TRUE);} +Error in is.vector(x, mode) : invalid 'mode' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector +#{is.vector(c(1,2), c("sss", "dddd"));} +Error in is.vector(x, mode) : invalid 'mode' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector #{is.vector(c(TRUE,FALSE),"logical");} [1] TRUE @@ -25042,6 +25430,10 @@ attr(,"origin") [1] "(Intercept)" "gravity" "ph" "osmo" "conduct" [6] "urea" "log(calc)" +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply +#{ .Internal(lapply(1:4, 42)) } +Error: attempt to apply non-function + ##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply #{ f <- function() { lapply(c(X="a",Y="b"), function(x) { c(a=x) }) } ; f() } $X @@ -25597,6 +25989,22 @@ Error: unexpected symbol in "argv <- list(list('Residuals vs Fitted', 'Normal Q- #argv <- list(c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE));length(argv[[1]]); [1] 260 +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengthassign.testArgsCasts +#{ x<-c(42, 1); length(x)<-'3'; x } +[1] 42 1 NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengthassign.testArgsCasts +#{ x<-c(42, 1); length(x)<-3.1; x } +[1] 42 1 NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengthassign.testArgsCasts +#{ x<-c(42, 1); length(x)<-c(1,2) } +Error in length(x) <- c(1, 2) : invalid value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengthassign.testArgsCasts +#{ x<-quote(a); length(x)<-2 } +Error in length(x) <- 2 : invalid argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_lengthassign.testLengthUpdate #{ x <- 1 ; f <- function() { length(x) <<- 2 } ; f() ; x } [1] 1 NA @@ -25718,6 +26126,56 @@ list() #argv <- structure(list(1:3, value = TRUE), .Names = c('', 'value'));do.call('length<-', argv) Error in do.call("length<-", argv) : invalid value +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengths.basics +#lengths(1:11) + [1] 1 1 1 1 1 1 1 1 1 1 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengths.basics +#lengths(NULL) +integer(0) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengths.basics +#lengths(c(1,2,3)) +[1] 1 1 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengths.basics +#lengths(list(1, c(1,2), 1:3)) +[1] 1 2 3 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengths.basics +#lengths(list(1, list(1, c(1,2)), 1:3)) +[1] 1 2 3 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengths.withNames +#lengths(list(a=1, b=c(1,2))) +a b +1 2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengths.withNames +#lengths(list(a=1, b=c(1,2)), use.names=FALSE) +[1] 1 2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengths.withNames +#lengths(matrix(1:4, nrow=2, ncol=2, dimnames=list(c('a', 'b'), c('d', 'e')))) +[1] 1 1 1 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengths.withNames +#x<-c(1,2); names(x) <- c('a', 'b'); lengths(x) +a b +1 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengths.withNames +#x<-c(1,2); names(x) <- c('a', 'b'); lengths(x, use.names=FALSE) +[1] 1 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengths.wrongArgs +#lengths(42, use.names='as') +Error in lengths(42, use.names = "as") : invalid 'USE.NAMES' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lengths.wrongArgs +#lengths(quote(a)) +Error in lengths(quote(a)) : 'x' must be a list or atomic vector + ##com.oracle.truffle.r.test.builtins.TestBuiltin_levels.testLevels #{ x <- 1 ; levels(x)<-"a"; levels(x);} [1] "a" @@ -26445,7 +26903,7 @@ TRUE ##com.oracle.truffle.r.test.builtins.TestBuiltin_list.testlist18 #argv <- list(date = structure(1065672000, class = c('POSIXct', 'POSIXt'), tzone = ''));list(argv[[1]]); [[1]] -[1] "2003-10-09 06:00:00 CEST" +[1] "2003-10-09 04:00:00 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_list.testlist19 @@ -27330,7 +27788,7 @@ attr(,"class") ##com.oracle.truffle.r.test.builtins.TestBuiltin_list.testlist52 #argv <- list(structure(1386392034.50546, class = c('POSIXct', 'POSIXt')));list(argv[[1]]); [[1]] -[1] "2013-12-07 05:53:54 CET" +[1] "2013-12-07 04:53:54 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_list.testlist53 @@ -27744,7 +28202,9 @@ character(0) #argv <- list('.', '^CITATION.*', FALSE, FALSE, TRUE, FALSE, FALSE, FALSE); .Internal(list.files(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]])) [1] "com.oracle.truffle.r.native/gnur/R-3.2.4/library/base/CITATION" [2] "com.oracle.truffle.r.native/gnur/R-3.2.4/src/library/base/inst/CITATION" -[3] "library/base/CITATION" +[3] "com.oracle.truffle.r.release/library/base/CITATION" +[4] "com.oracle.truffle.r.test/rpackages/testrlibs_user/MASS/CITATION" +[5] "library/base/CITATION" ##com.oracle.truffle.r.test.builtins.TestBuiltin_listfiles.testlistfiles4 #argv <- list('mgcv', NULL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE); .Internal(list.files(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]])) @@ -27894,6 +28354,33 @@ 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 +#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' + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lockEnvironment.testlockEnvironment +#e <- new.env(); e$a <- 'foo'; lockEnvironment(e, 'a'); e$b <- 123 +Error in e$b <- 123 : cannot add bindings to a locked environment + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lockEnvironment.testlockEnvironment +#e <- new.env(); e$a <- 'foo'; lockEnvironment(e, FALSE); e$a <- 123 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lockEnvironment.testlockEnvironment +#e <- new.env(); e$a <- 'foo'; lockEnvironment(e, FALSE); e$b <- 123 +Error in e$b <- 123 : cannot add bindings to a locked environment + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lockEnvironment.testlockEnvironment +#e <- new.env(); e$a <- 'foo'; lockEnvironment(e, logical()); e$a <- 123 +Error in e$a <- 123 : cannot change value of locked binding for 'a' + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lockEnvironment.testlockEnvironment +#e <- new.env(); e$a <- 'foo'; lockEnvironment(e, logical()); e$b <- 123 +Error in e$b <- 123 : cannot add bindings to a locked environment + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lockEnvironment.testlockEnvironment +#lockEnvironment('foo', TRUE) +Error in lockEnvironment("foo", TRUE) : not an environment + ##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLog #{ log(0) } [1] -Inf @@ -27906,6 +28393,14 @@ Error in eval(expr, envir, enclos) : object 'y' not found #{ log(c(0,1)) } [1] -Inf 0 +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLog +#{ log(c(2,3), 0/0) } +[1] NaN NaN + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLog +#{ log(c(2,3), NA) } +[1] NA NA + ##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLog #{ round( log(10,), digits = 5 ) } [1] 2.30259 @@ -28101,6 +28596,26 @@ Error in log1p(c(1 + (0+1i), -1 - (0+1i))) : #argv <- structure(list(length = 0), .Names = 'length');do.call('logical', argv) logical(0) +##com.oracle.truffle.r.test.builtins.TestBuiltin_ls.basicTests +#e <- new.env(); assign('.x',42,e); assign('y','42',e); ls(envir=e, all.names=FALSE) +[1] "y" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_ls.basicTests +#e <- new.env(); assign('.x',42,e); assign('y','42',e); ls(envir=e, all.names=TRUE) +[1] ".x" "y" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_ls.basicTests +#f <- function(){ x <- 42; a <- 'two'; ls() }; f() +[1] "a" "x" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_ls.invalidArgTests +#.Internal(ls(42, TRUE, TRUE)) +Error: invalid 'envir' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_makenames.testMakeNames +#{ .Internal(make.names(42, F)) } +Error: non-character names + ##com.oracle.truffle.r.test.builtins.TestBuiltin_makenames.testMakeNames #{ make.names("$") } [1] "X." @@ -28214,6 +28729,30 @@ character(0) #argv <- list(c('Subject', 'predict.fixed', 'predict.Subject'), TRUE); .Internal(make.names(argv[[1]], argv[[2]])) [1] "Subject" "predict.fixed" "predict.Subject" +##com.oracle.truffle.r.test.builtins.TestBuiltin_makeunique.testMakeUnique +#{ .Internal(make.unique(NULL, ".")) } +Error: 'names' must be a character vector + +##com.oracle.truffle.r.test.builtins.TestBuiltin_makeunique.testMakeUnique +#{ .Internal(make.unique(c("7", "42"), 42)) } +Error: 'sep' must be a character string + +##com.oracle.truffle.r.test.builtins.TestBuiltin_makeunique.testMakeUnique +#{ .Internal(make.unique(c("7", "42"), NULL)) } +Error: 'sep' must be a character string + +##com.oracle.truffle.r.test.builtins.TestBuiltin_makeunique.testMakeUnique +#{ .Internal(make.unique(c("7", "42"), c(".", "."))) } +Error: 'sep' must be a character string + +##com.oracle.truffle.r.test.builtins.TestBuiltin_makeunique.testMakeUnique +#{ .Internal(make.unique(c("7", "42"), character())) } +Error: 'sep' must be a character string + +##com.oracle.truffle.r.test.builtins.TestBuiltin_makeunique.testMakeUnique +#{ .Internal(make.unique(c(7, 42), ".")) } +Error: 'names' must be a character vector + ##com.oracle.truffle.r.test.builtins.TestBuiltin_makeunique.testMakeUnique #{ make.unique("a") } [1] "a" @@ -28425,16 +28964,16 @@ integer(0) [1] 2 4 5 2 1 ##com.oracle.truffle.r.test.builtins.TestBuiltin_match.testMatch -#{ match(c(7, 42), NULL } -Error: unexpected '}' in "{ match(c(7, 42), NULL }" +#{ match(c(7, 42), NULL) } +[1] NA NA ##com.oracle.truffle.r.test.builtins.TestBuiltin_match.testMatch -#{ match(c(7, 42), NULL, 1L } -Error: unexpected '}' in "{ match(c(7, 42), NULL, 1L }" +#{ match(c(7, 42), NULL, 1L) } +[1] 1 1 ##com.oracle.truffle.r.test.builtins.TestBuiltin_match.testMatch -#{ match(c(7, 42), NULL, integer() } -Error: unexpected '}' in "{ match(c(7, 42), NULL, integer() }" +#{ match(c(7, 42), NULL, integer()) } +[1] NA NA ##com.oracle.truffle.r.test.builtins.TestBuiltin_match.testMatch #{ match(factor(c("a", "b")), factor(c("c", "b", "a", "b", "c", "a"))) } @@ -29899,33 +30438,33 @@ In max(argv[[1]]) : no non-missing arguments to max; returning -Inf [1] 1.3e+100 ##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testmax16 -#argv <- list(structure(c(11368.8306749654, 11347.7238090355, 11341.9182102121, 11392.4878842821, 11367.3445285107, 11337.9245694652, 11332.0560643654, 11356.4682624019, 11387.6852128883, 11364.9132677, 11391.3319486445, 11374.2254758319, 11347.9708838458, 11353.2031583386, 11333.3748092474, 11323.9154302836, 11373.0896246266, 11330.2228965024, 11354.2399044028, 11367.8070731596, 11392.4287034031, 11357.6915504499, 11356.9044667059, 11335.1409634408, 11375.8374661156, 11354.7726842454, 11358.781884864, 11337.5281579299, 11339.0060699913, 11364.6998397419, 11363.2410538797, 11328.3945066198, 11325.487840571, 11367.9956844538, 11388.0030639744, 11364.8664695648, 11362.2630523606, 11359.821940674, 11391.9566656714, 11358.5349275633, 11370.7951655071, 11365.1078852355, 11339.7208074429, 11341.0716148671, 11374.0516736354, 11354.6799581982, 11335.2588737891, 11375.2688788734, 11330.349134828, 11383.518146432, 11366.0251480173, 11362.0011677193, 11346.0144123337, 11354.7192011815, 11358.0308680837, 11335.6606452791, 11360.0741421962, 11328.2693021996, 11342.4429152855, 11337.8889663466, 11342.9353336683, 11385.6565872063, 11354.2364726327, 11377.5989422849, 11384.6433324409, 11351.9186946652, 11327.4665936357, 11346.4841244179, 11373.6608162634, 11346.6330733448, 11367.1289885738, 11381.8430187805, 11382.9292165297, 11350.3951496719, 11349.6345719923, 11385.6811798196, 11368.1021034038, 11374.8755054101, 11365.3712412571, 11386.2157128048, 11343.5611108569, 11336.3882076922, 11385.0515660313, 11358.2337640012, 11384.3940280117, 11336.2435535709, 11376.0672136671, 11373.7149224868, 11389.0607372806, 11361.3352610911, 11372.8220707406, 11350.2233569878, 11330.0611188328, 11387.9111462012, 11342.8262750218, 11364.340121117, 11330.7252423461, 11381.8354922482, 11345.257457911, 11377.7995935893), class = 'Date'), na.rm = TRUE);max(argv[[1]],argv[[2]]); -[1] "2001-03-11" +#argv <- list(structure(c(11368.8306749654, 11347.7238090355, 11341.9182102121, 11392.4878842821, 11367.3445285107, 11337.9245694652, 11332.0560643654, 11356.4682624019, 11387.6852128883, 11364.9132677, 11391.3319486445, 11374.2254758319, 11347.9708838458, 11353.2031583386, 11333.3748092474, 11323.9154302836, 11373.0896246266, 11330.2228965024, 11354.2399044028, 11367.8070731596, 11392.4287034031, 11357.6915504499, 11356.9044667059, 11335.1409634408, 11375.8374661156, 11354.7726842454, 11358.781884864, 11337.5281579299, 11339.0060699913, 11364.6998397419, 11363.2410538797, 11328.3945066198, 11325.487840571, 11367.9956844538, 11388.0030639744, 11364.8664695648, 11362.2630523606, 11359.821940674, 11391.9566656714, 11358.5349275633, 11370.7951655071, 11365.1078852355, 11339.7208074429, 11341.0716148671, 11374.0516736354, 11354.6799581982, 11335.2588737891, 11375.2688788734, 11330.349134828, 11383.518146432, 11366.0251480173, 11362.0011677193, 11346.0144123337, 11354.7192011815, 11358.0308680837, 11335.6606452791, 11360.0741421962, 11328.2693021996, 11342.4429152855, 11337.8889663466, 11342.9353336683, 11385.6565872063, 11354.2364726327, 11377.5989422849, 11384.6433324409, 11351.9186946652, 11327.4665936357, 11346.4841244179, 11373.6608162634, 11346.6330733448, 11367.1289885738, 11381.8430187805, 11382.9292165297, 11350.3951496719, 11349.6345719923, 11385.6811798196, 11368.1021034038, 11374.8755054101, 11365.3712412571, 11386.2157128048, 11343.5611108569, 11336.3882076922, 11385.0515660313, 11358.2337640012, 11384.3940280117, 11336.2435535709, 11376.0672136671, 11373.7149224868, 11389.0607372806, 11361.3352610911, 11372.8220707406, 11350.2233569878, 11330.0611188328, 11387.9111462012, 11342.8262750218, 11364.340121117, 11330.7252423461, 11381.8354922482, 11345.257457911, 11377.7995935893), class = 'Date'));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE); +[1] "2001-02-15" ##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testmax17 -#argv <- list(structure(c(3L, 2L, 1L), .Label = c('A', 'B', 'C'), class = c('ordered', 'factor')), na.rm = FALSE);max(argv[[1]],argv[[2]]); -Error in Summary.ordered(c(3L, 2L, 1L), FALSE, na.rm = FALSE) : - 'max' is only meaningful for ordered factors if all arguments have the same level sets +#argv <- list(structure(c(3L, 2L, 1L), .Label = c('A', 'B', 'C'), class = c('ordered', 'factor')));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] C +Levels: A < B < C ##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testmax18 -#argv <- list(structure(c(1338544800L, 1338566400L, 1338588000L, 1338609600L, 1338631200L, 1338652800L, 1338674400L, 1338696000L, 1338717600L, 1338739200L, 1338760800L, 1338782400L, 1338804000L, 1338825600L, 1338847200L, 1338868800L, 1338890400L, 1338912000L, 1338933600L, 1338955200L, 1338976800L, 1338998400L, 1339020000L, 1339041600L), class = c('POSIXct', 'POSIXt'), tzone = ''), na.rm = TRUE);max(argv[[1]],argv[[2]]); -[1] "2012-06-07 06:00:00 CEST" +#argv <- list(structure(c(1338544800L, 1338566400L, 1338588000L, 1338609600L, 1338631200L, 1338652800L, 1338674400L, 1338696000L, 1338717600L, 1338739200L, 1338760800L, 1338782400L, 1338804000L, 1338825600L, 1338847200L, 1338868800L, 1338890400L, 1338912000L, 1338933600L, 1338955200L, 1338976800L, 1338998400L, 1339020000L, 1339041600L), class = c('POSIXct', 'POSIXt'), tzone = ''));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE); +[1] "2012-06-01 16:00:00 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testmax19 -#argv <- list(structure(list(c(1L, 2L, 4L), 1:3, c(2L, 1L)), class = c('package_version', 'numeric_version')), na.rm = FALSE);max(argv[[1]],argv[[2]]); -Error: invalid version specification ‘FALSE’ +#argv <- list(structure(list(c(1L, 2L, 4L), 1:3, c(2L, 1L)), class = c('package_version', 'numeric_version')));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] ‘1.2.4’ ##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testmax2 -#argv <- list(structure(c(1208822400, 1209168000, 1208822400, 1209168000), class = c('POSIXct', 'POSIXt')), na.rm = TRUE);max(argv[[1]],argv[[2]]); -[1] "2008-04-26 02:00:00 CEST" +#argv <- list(structure(c(1208822400, 1209168000, 1208822400, 1209168000), class = c('POSIXct', 'POSIXt')));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE); +[1] "2008-04-26 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testmax20 -#argv <- list(structure(c(1208822400, 1209168000), class = c('POSIXct', 'POSIXt'), tzone = 'GMT'), na.rm = FALSE);max(argv[[1]],argv[[2]]); +#argv <- list(structure(c(1208822400, 1209168000), class = c('POSIXct', 'POSIXt'), tzone = 'GMT'));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); [1] "2008-04-26 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testmax21 -#argv <- list(structure(c(13823, NA), class = 'Date'), na.rm = TRUE);max(argv[[1]],argv[[2]]); -[1] NA +#argv <- list(structure(c(13823, NA), class = 'Date'));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE); +[1] "2007-11-06" ##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testmax22 #argv <- list(structure(c(7L, 4L, 3L), .Dim = 3L, .Dimnames = structure(list(c('0', '1', '5')), .Names = ''), class = 'table'));max(argv[[1]]); @@ -29982,9 +30521,8 @@ In max() : no non-missing arguments to max; returning -Inf [1] 8 ##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testmax9 -#argv <- list(structure(list(x = c(-1, 1, 1, -1, -1, 1, 1, -1), y = c(-0.701149425287356, -0.701149425287356, -0.701149425287356, -0.701149425287356, 0.701149425287356, 0.701149425287356, 0.701149425287356, 0.701149425287356), z = c(-0.4, -0.4, 0.4, 0.4, -0.4, -0.4, 0.4, 0.4)), .Names = c('x', 'y', 'z'), row.names = c(NA, -8L), class = 'data.frame'), na.rm = FALSE);max(argv[[1]],argv[[2]]); -Error in FUN(X[[i]], ...) : - only defined on a data frame with all numeric variables +#argv <- list(structure(list(x = c(-1, 1, 1, -1, -1, 1, 1, -1), y = c(-0.701149425287356, -0.701149425287356, -0.701149425287356, -0.701149425287356, 0.701149425287356, 0.701149425287356, 0.701149425287356, 0.701149425287356), z = c(-0.4, -0.4, 0.4, 0.4, -0.4, -0.4, 0.4, 0.4)), .Names = c('x', 'y', 'z'), row.names = c(NA, -8L), class = 'data.frame'));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] 1 ##com.oracle.truffle.r.test.builtins.TestBuiltin_maxcol.testmaxcol1 #argv <- list(structure(c(80.2, 17, 15, 12, 9.96, 22.2, 83.1, 45.1, 6, 9, 84.84, 22.2, 92.5, 39.7, 5, 5, 93.4, 20.2, 85.8, 36.5, 12, 7, 33.77, 20.3, 76.9, 43.5, 17, 15, 5.16, 20.6, 76.1, 35.3, 9, 7, 90.57, 26.6, 83.8, 70.2, 16, 7, 92.85, 23.6, 92.4, 67.8, 14, 8, 97.16, 24.9, 82.4, 53.3, 12, 7, 97.67, 21, 82.9, 45.2, 16, 13, 91.38, 24.4, 87.1, 64.5, 14, 6, 98.61, 24.5, 64.1, 62, 21, 12, 8.52, 16.5, 66.9, 67.5, 14, 7, 2.27, 19.1, 68.9, 60.7, 19, 12, 4.43, 22.7, 61.7, 69.3, 22, 5, 2.82, 18.7, 68.3, 72.6, 18, 2, 24.2, 21.2, 71.7, 34, 17, 8, 3.3, 20, 55.7, 19.4, 26, 28, 12.11, 20.2, 54.3, 15.2, 31, 20, 2.15, 10.8, 65.1, 73, 19, 9, 2.84, 20, 65.5, 59.8, 22, 10, 5.23, 18, 65, 55.1, 14, 3, 4.52, 22.4, 56.6, 50.9, 22, 12, 15.14, 16.7, 57.4, 54.1, 20, 6, 4.2, 15.3, 72.5, 71.2, 12, 1, 2.4, 21, 74.2, 58.1, 14, 8, 5.23, 23.8, 72, 63.5, 6, 3, 2.56, 18, 60.5, 60.8, 16, 10, 7.72, 16.3, 58.3, 26.8, 25, 19, 18.46, 20.9, 65.4, 49.5, 15, 8, 6.1, 22.5, 75.5, 85.9, 3, 2, 99.71, 15.1, 69.3, 84.9, 7, 6, 99.68, 19.8, 77.3, 89.7, 5, 2, 100, 18.3, 70.5, 78.2, 12, 6, 98.96, 19.4, 79.4, 64.9, 7, 3, 98.22, 20.2, 65, 75.9, 9, 9, 99.06, 17.8, 92.2, 84.6, 3, 3, 99.46, 16.3, 79.3, 63.1, 13, 13, 96.83, 18.1, 70.4, 38.4, 26, 12, 5.62, 20.3, 65.7, 7.7, 29, 11, 13.79, 20.5, 72.7, 16.7, 22, 13, 11.22, 18.9, 64.4, 17.6, 35, 32, 16.92, 23, 77.6, 37.6, 15, 7, 4.97, 20, 67.6, 18.7, 25, 7, 8.65, 19.5, 35, 1.2, 37, 53, 42.34, 18, 44.7, 46.6, 16, 29, 50.43, 18.2, 42.8, 27.7, 22, 29, 58.33, 19.3), .Dim = c(6L, 47L), .Dimnames = list(c('Fertility', 'Agriculture', 'Examination', 'Education', 'Catholic', 'Infant.Mortality'), c('Courtelary', 'Delemont', 'Franches-Mnt', 'Moutier', 'Neuveville', 'Porrentruy', 'Broye', 'Glane', 'Gruyere', 'Sarine', 'Veveyse', 'Aigle', 'Aubonne', 'Avenches', 'Cossonay', 'Echallens', 'Grandson', 'Lausanne', 'La Vallee', 'Lavaux', 'Morges', 'Moudon', 'Nyone', 'Orbe', 'Oron', 'Payerne', 'Paysd'enhaut', 'Rolle', 'Vevey', 'Yverdon', 'Conthey', 'Entremont', 'Herens', 'Martigwy', 'Monthey', 'St Maurice', 'Sierre', 'Sion', 'Boudry', 'La Chauxdfnd', 'Le Locle', 'Neuchatel', 'Val de Ruz', 'ValdeTravers', 'V. De Geneve', 'Rive Droite', 'Rive Gauche'))), 1L); .Internal(max.col(argv[[1]], argv[[2]])) @@ -30132,7 +30670,7 @@ In mean.default(x = c(2L, 1L, 2L, 2L)) : ##com.oracle.truffle.r.test.builtins.TestBuiltin_meanPOSIXct.testmeanPOSIXct1 #argv <- structure(list(x = structure(1412795929.08562, class = c('POSIXct', 'POSIXt'))), .Names = 'x');do.call('mean.POSIXct', argv) -[1] "2014-10-08 21:18:49 CEST" +[1] "2014-10-08 19:18:49 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_meandefault.testmeandefault1 #argv <- structure(list(x = structure(c(2L, 1L, 2L, 2L), .Label = c('FALSE', 'TRUE'), class = 'factor')), .Names = 'x');do.call('mean.default', argv) @@ -30149,6 +30687,29 @@ Time difference of 31 days #argv <- structure(list(from = as.raw(c(253, 55, 122, 88, 90, 0, 0, 1, 105, 34, 222, 54, 2, 0, 33, 1, 28, 0, 0, 0, 16, 207, 88, 204, 224, 7, 207, 0, 28, 93, 0, 24, 140, 130, 182, 196, 17, 52, 92, 78, 225, 221, 115, 179, 63, 98, 20, 119, 183, 90, 101, 43, 5, 112, 179, 75, 69, 222, 0, 0, 155, 136, 185, 16, 0, 1, 52, 208, 15, 0, 0, 0, 105, 254, 40, 141, 62, 48, 13, 139, 2, 0, 0, 0, 0, 1, 89, 90)), type = 'xz', asChar = TRUE), .Names = c('from', 'type', 'asChar'));do.call('memDecompress', argv) [1] "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" +##com.oracle.truffle.r.test.builtins.TestBuiltin_merge.testExamplesFromHelp +#x <- data.frame(k1 = c(NA,NA,3,4,5), k2 = c(1,NA,NA,4,5), data = 1:5);y <- data.frame(k1 = c(NA,2,NA,4,5), k2 = c(NA,NA,3,4,5), data = 1:5);merge(x, y, by = 'k1') + k1 k2.x data.x k2.y data.y +1 4 4 4 4 4 +2 5 5 5 5 5 +3 NA 1 1 NA 1 +4 NA 1 1 3 3 +5 NA NA 2 NA 1 +6 NA NA 2 3 3 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_merge.testExamplesFromHelp +#x <- data.frame(k1 = c(NA,NA,3,4,5), k2 = c(1,NA,NA,4,5), data = 1:5);y <- data.frame(k1 = c(NA,2,NA,4,5), k2 = c(NA,NA,3,4,5), data = 1:5);merge(x, y, by = 'k2', incomparables = NA) + k2 k1.x data.x k1.y data.y +1 4 4 4 4 4 +2 5 5 5 5 5 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_merge.testExamplesFromHelp +#x <- data.frame(k1 = c(NA,NA,3,4,5), k2 = c(1,NA,NA,4,5), data = 1:5);y <- data.frame(k1 = c(NA,2,NA,4,5), k2 = c(NA,NA,3,4,5), data = 1:5);merge(x, y, by = c('k1','k2')) + k1 k2 data.x data.y +1 4 4 4 4 +2 5 5 5 5 +3 NA NA 2 1 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_merge.testmerge1 #argv <- list(c(0L, 0L, 0L, 0L, 0L), 0L, FALSE, TRUE); .Internal(merge(argv[[1]], argv[[2]], argv[[3]], argv[[4]])) $xi @@ -30560,12 +31121,12 @@ Warning message: In min() : no non-missing arguments to min; returning Inf ##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testmin14 -#argv <- list(structure(c(13823, NA), class = 'Date'), na.rm = TRUE);min(argv[[1]],argv[[2]]); -[1] NA +#argv <- list(structure(c(13823, NA), class = 'Date'));min(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE); +[1] "2007-11-06" ##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testmin15 -#argv <- list(structure(c(1208822400, 1209168000), class = c('POSIXct', 'POSIXt'), tzone = 'GMT'), na.rm = FALSE);min(argv[[1]],argv[[2]]); -[1] "1970-01-01 GMT" +#argv <- list(structure(c(1208822400, 1209168000), class = c('POSIXct', 'POSIXt'), tzone = 'GMT'));min(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] "2008-04-22 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testmin16 #argv <- list(3L, 7);min(argv[[1]],argv[[2]]); @@ -30606,25 +31167,25 @@ In min(argv[[1]]) : no non-missing arguments to min; returning Inf [1] NA ##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testmin5 -#argv <- list(structure(list(c(1L, 2L, 4L), 1:3, c(2L, 1L)), class = c('package_version', 'numeric_version')), na.rm = FALSE);min(argv[[1]],argv[[2]]); -Error: invalid version specification ‘FALSE’ +#argv <- list(structure(list(c(1L, 2L, 4L), 1:3, c(2L, 1L)), class = c('package_version', 'numeric_version')));min(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] ‘1.2.3’ ##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testmin6 -#argv <- list(structure(c(1338544800L, 1338566400L, 1338588000L, 1338609600L, 1338631200L, 1338652800L, 1338674400L, 1338696000L, 1338717600L, 1338739200L, 1338760800L, 1338782400L, 1338804000L, 1338825600L, 1338847200L, 1338868800L, 1338890400L, 1338912000L, 1338933600L, 1338955200L, 1338976800L, 1338998400L, 1339020000L, 1339041600L), class = c('POSIXct', 'POSIXt'), tzone = ''), na.rm = TRUE);min(argv[[1]],argv[[2]]); -[1] "1970-01-01 01:00:01 CET" +#argv <- list(structure(c(1338544800L, 1338566400L, 1338588000L, 1338609600L, 1338631200L, 1338652800L, 1338674400L, 1338696000L, 1338717600L, 1338739200L, 1338760800L, 1338782400L, 1338804000L, 1338825600L, 1338847200L, 1338868800L, 1338890400L, 1338912000L, 1338933600L, 1338955200L, 1338976800L, 1338998400L, 1339020000L, 1339041600L), class = c('POSIXct', 'POSIXt'), tzone = ''));min(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE); +[1] "2012-06-01 10:00:00 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testmin7 #argv <- list(1.234e+100);min(argv[[1]]); [1] 1.234e+100 ##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testmin8 -#argv <- list(structure(c(3L, 2L, 1L), .Label = c('A', 'B', 'C'), class = c('ordered', 'factor')), na.rm = FALSE);min(argv[[1]],argv[[2]]); -Error in Summary.ordered(c(3L, 2L, 1L), FALSE, na.rm = FALSE) : - 'min' is only meaningful for ordered factors if all arguments have the same level sets +#argv <- list(structure(c(3L, 2L, 1L), .Label = c('A', 'B', 'C'), class = c('ordered', 'factor')));min(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] B +Levels: A < B < C ##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testmin9 -#argv <- list(structure(c(11368.8306749654, 11347.7238090355, 11341.9182102121, 11392.4878842821, 11367.3445285107, 11337.9245694652, 11332.0560643654, 11356.4682624019, 11387.6852128883, 11364.9132677, 11391.3319486445, 11374.2254758319, 11347.9708838458, 11353.2031583386, 11333.3748092474, 11323.9154302836, 11373.0896246266, 11330.2228965024, 11354.2399044028, 11367.8070731596, 11392.4287034031, 11357.6915504499, 11356.9044667059, 11335.1409634408, 11375.8374661156, 11354.7726842454, 11358.781884864, 11337.5281579299, 11339.0060699913, 11364.6998397419, 11363.2410538797, 11328.3945066198, 11325.487840571, 11367.9956844538, 11388.0030639744, 11364.8664695648, 11362.2630523606, 11359.821940674, 11391.9566656714, 11358.5349275633, 11370.7951655071, 11365.1078852355, 11339.7208074429, 11341.0716148671, 11374.0516736354, 11354.6799581982, 11335.2588737891, 11375.2688788734, 11330.349134828, 11383.518146432, 11366.0251480173, 11362.0011677193, 11346.0144123337, 11354.7192011815, 11358.0308680837, 11335.6606452791, 11360.0741421962, 11328.2693021996, 11342.4429152855, 11337.8889663466, 11342.9353336683, 11385.6565872063, 11354.2364726327, 11377.5989422849, 11384.6433324409, 11351.9186946652, 11327.4665936357, 11346.4841244179, 11373.6608162634, 11346.6330733448, 11367.1289885738, 11381.8430187805, 11382.9292165297, 11350.3951496719, 11349.6345719923, 11385.6811798196, 11368.1021034038, 11374.8755054101, 11365.3712412571, 11386.2157128048, 11343.5611108569, 11336.3882076922, 11385.0515660313, 11358.2337640012, 11384.3940280117, 11336.2435535709, 11376.0672136671, 11373.7149224868, 11389.0607372806, 11361.3352610911, 11372.8220707406, 11350.2233569878, 11330.0611188328, 11387.9111462012, 11342.8262750218, 11364.340121117, 11330.7252423461, 11381.8354922482, 11345.257457911, 11377.7995935893), class = 'Date'), na.rm = TRUE);min(argv[[1]],argv[[2]]); -[1] "1970-01-02" +#argv <- list(structure(c(11368.8306749654, 11347.7238090355, 11341.9182102121, 11392.4878842821, 11367.3445285107, 11337.9245694652, 11332.0560643654, 11356.4682624019, 11387.6852128883, 11364.9132677, 11391.3319486445, 11374.2254758319, 11347.9708838458, 11353.2031583386, 11333.3748092474, 11323.9154302836, 11373.0896246266, 11330.2228965024, 11354.2399044028, 11367.8070731596, 11392.4287034031, 11357.6915504499, 11356.9044667059, 11335.1409634408, 11375.8374661156, 11354.7726842454, 11358.781884864, 11337.5281579299, 11339.0060699913, 11364.6998397419, 11363.2410538797, 11328.3945066198, 11325.487840571, 11367.9956844538, 11388.0030639744, 11364.8664695648, 11362.2630523606, 11359.821940674, 11391.9566656714, 11358.5349275633, 11370.7951655071, 11365.1078852355, 11339.7208074429, 11341.0716148671, 11374.0516736354, 11354.6799581982, 11335.2588737891, 11375.2688788734, 11330.349134828, 11383.518146432, 11366.0251480173, 11362.0011677193, 11346.0144123337, 11354.7192011815, 11358.0308680837, 11335.6606452791, 11360.0741421962, 11328.2693021996, 11342.4429152855, 11337.8889663466, 11342.9353336683, 11385.6565872063, 11354.2364726327, 11377.5989422849, 11384.6433324409, 11351.9186946652, 11327.4665936357, 11346.4841244179, 11373.6608162634, 11346.6330733448, 11367.1289885738, 11381.8430187805, 11382.9292165297, 11350.3951496719, 11349.6345719923, 11385.6811798196, 11368.1021034038, 11374.8755054101, 11365.3712412571, 11386.2157128048, 11343.5611108569, 11336.3882076922, 11385.0515660313, 11358.2337640012, 11384.3940280117, 11336.2435535709, 11376.0672136671, 11373.7149224868, 11389.0607372806, 11361.3352610911, 11372.8220707406, 11350.2233569878, 11330.0611188328, 11387.9111462012, 11342.8262750218, 11364.340121117, 11330.7252423461, 11381.8354922482, 11345.257457911, 11377.7995935893), class = 'Date'));min(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE); +[1] "2001-01-25" ##com.oracle.truffle.r.test.builtins.TestBuiltin_minus_Date.testminus_Date1 #argv <- structure(list(e1 = structure(14580, class = 'Date'), e2 = structure(1, units = 'days', class = 'difftime')), .Names = c('e1', 'e2'));do.call('-.Date', argv) @@ -30762,6 +31323,10 @@ NULL #{ x<-c(1,2,3); dim(x)<-3; dimnames(x)<-list(c(11,12,13)); names(x) } [1] "11" "12" "13" +##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testNames +#{ y<-c(d="e"); attr(y, "foo")<-"foo"; x<-c(42); names(x)<-y; attributes(names(x)) } +NULL + ##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testnames1 #argv <- list(structure(list(size = 113, isdir = FALSE, mode = structure(436L, class = 'octmode'), mtime = structure(1395082088.72988, class = c('POSIXct', 'POSIXt')), ctime = structure(1395082088.72988, class = c('POSIXct', 'POSIXt')), atime = structure(1395082088.77388, class = c('POSIXct', 'POSIXt')), uid = 1001L, gid = 1001L, uname = 'roman', grname = 'roman'), .Names = c('size', 'isdir', 'mode', 'mtime', 'ctime', 'atime', 'uid', 'gid', 'uname', 'grname'), class = 'data.frame', row.names = '/tmp/RtmptPgrXI/file55711ba85492'));names(argv[[1]]); [1] "size" "isdir" "mode" "mtime" "ctime" "atime" "uid" "gid" @@ -31630,12 +32195,12 @@ Wyoming 97203 West [1] NA ##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNChar -#{ .Internal(nchar('ff', 'chars', FALSE) } -Error: unexpected '}' in "{ .Internal(nchar('ff', 'chars', FALSE) }" +#{ .Internal(nchar('ff', 'chars', FALSE)) } +[1] 2 ##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNChar -#{ .Internal(nchar(c(10,130), 'chars', FALSE) } -Error: unexpected '}' in "{ .Internal(nchar(c(10,130), 'chars', FALSE) }" +#{ .Internal(nchar(c(10,130), 'chars', FALSE)) } +[1] 2 3 ##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNChar #{ nchar(c("hello", "hi")) } @@ -31701,6 +32266,27 @@ Error in argv[[4]] : subscript out of bounds #argv <- structure(list(x = structure(list(pop15 = c(29.35, 23.32, 23.8, 41.89, 42.19, 31.72, 39.74, 44.75, 46.64, 47.64, 24.42, 46.31, 27.84, 25.06, 23.31, 25.62, 46.05, 47.32, 34.03, 41.31, 31.16, 24.52, 27.01, 41.74, 21.8, 32.54, 25.95, 24.71, 32.61, 45.04, 43.56, 41.18, 44.19, 46.26, 28.96, 31.94, 31.92, 27.74, 21.44, 23.49, 43.42, 46.12, 23.27, 29.81, 46.4, 45.25, 41.12, 28.13, 43.69, 47.2), pop75 = c(2.87, 4.41, 4.43, 1.67, 0.83, 2.85, 1.34, 0.67, 1.06, 1.14, 3.93, 1.19, 2.37, 4.7, 3.35, 3.1, 0.87, 0.58, 3.08, 0.96, 4.19, 3.48, 1.91, 0.91, 3.73, 2.47, 3.67, 3.25, 3.17, 1.21, 1.2, 1.05, 1.28, 1.12, 2.85, 2.28, 1.52, 2.87, 4.54, 3.73, 1.08, 1.21, 4.46, 3.43, 0.9, 0.56, 1.73, 2.72, 2.07, 0.66), dpi = c(2329.68, 1507.99, 2108.47, 189.13, 728.47, 2982.88, 662.86, 289.52, 276.65, 471.24, 2496.53, 287.77, 1681.25, 2213.82, 2457.12, 870.85, 289.71, 232.44, 1900.1, 88.94, 1139.95, 1390, 1257.28, 207.68, 2449.39, 601.05, 2231.03, 1740.7, 1487.52, 325.54, 568.56, 220.56, 400.06, 152.01, 579.51, 651.11, 250.96, 768.79, 3299.49, 2630.96, 389.66, 249.87, 1813.93, 4001.89, 813.39, 138.33, 380.47, 766.54, 123.58, 242.69), ddpi = c(2.87, 3.93, 3.82, 0.22, 4.56, 2.43, 2.67, 6.51, 3.08, 2.8, 3.99, 2.19, 4.32, 4.52, 3.44, 6.28, 1.48, 3.19, 1.12, 1.54, 2.99, 3.54, 8.21, 5.81, 1.57, 8.12, 3.62, 7.66, 1.76, 2.48, 3.61, 1.03, 0.67, 2, 7.48, 2.19, 2, 4.35, 3.01, 2.7, 2.96, 1.13, 2.01, 2.45, 0.53, 5.14, 10.23, 1.88, 16.71, 5.08)), .Names = c('pop15', 'pop75', 'dpi', 'ddpi'), class = 'data.frame', row.names = c('Australia', 'Austria', 'Belgium', 'Bolivia', 'Brazil', 'Canada', 'Chile', 'China', 'Colombia', 'Costa Rica', 'Denmark', 'Ecuador', 'Finland', 'France', 'Germany', 'Greece', 'Guatamala', 'Honduras', 'Iceland', 'India', 'Ireland', 'Italy', 'Japan', 'Korea', 'Luxembourg', 'Malta', 'Norway', 'Netherlands', 'New Zealand', 'Nicaragua', 'Panama', 'Paraguay', 'Peru', 'Philippines', 'Portugal', 'South Africa', 'South Rhodesia', 'Spain', 'Sweden', 'Switzerland', 'Turkey', 'Tunisia', 'United Kingdom', 'United States', 'Venezuela', 'Zambia', 'Jamaica', 'Uruguay', 'Libya', 'Malaysia'))), .Names = 'x');do.call('ncol', argv) [1] 4 +##com.oracle.truffle.r.test.builtins.TestBuiltin_newenv.testnewenv +#e <- new.env(); e; parent.env(new.env(TRUE, e)) +<environment: 0x7ff8e986ea08> +<environment: 0x7ff8e986ea08> + +##com.oracle.truffle.r.test.builtins.TestBuiltin_newenv.testnewenv +#new.env() +<environment: 0x7fd14b800e98> + +##com.oracle.truffle.r.test.builtins.TestBuiltin_newenv.testnewenv +#new.env(1,,2) +<environment: 0x7ff87086ebc8> + +##com.oracle.truffle.r.test.builtins.TestBuiltin_newenv.testnewenv +#new.env(logical(),new.env(),1000) +<environment: 0x7ff11406d518> + +##com.oracle.truffle.r.test.builtins.TestBuiltin_newenv.testnewenv +#parent.env(new.env()) +<environment: R_GlobalEnv> + ##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext #{ ngettext(-1, "a", "b") } Error in ngettext(-1, "a", "b") : invalid 'n' argument @@ -31795,6 +32381,22 @@ 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('asdasd', NA), keepNA=FALSE) +[1] TRUE TRUE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.keepNATests +#nzchar(c('asdasd', NA), keepNA=TRUE) +[1] TRUE NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs +#nzchar(NULL) +logical(0) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs +#nzchar(list('x', 42, list('a'), list())) +[1] TRUE TRUE TRUE TRUE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.testnzchar1 #argv <- list('./myTst2/man/DocLink-class.Rd');nzchar(argv[[1]]); [1] TRUE @@ -31836,8 +32438,12 @@ logical(0) [1] TRUE ##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.testnzchar9 -#argv <- list(c(' \036 The other major change was an error for asymmetric loss matrices,', ' prompted by a user query. With L=loss asymmetric, the altered', ' priors were computed incorrectly - they were using L' instead of L.', ' Upshot - the tree would not not necessarily choose optimal splits', ' for the given loss matrix. Once chosen, splits were evaluated', ' correctly. The printed “improvement” values are of course the', ' wrong ones as well. It is interesting that for my little test', ' case, with L quite asymmetric, the early splits in the tree are', ' unchanged - a good split still looks good.'));nzchar(argv[[1]]); -Error: unexpected symbol in "argv <- list(c(' \036 The other major change was an error for asymmetric loss matrices,', ' prompted by a user query. With L=loss asymmetric, the altered', ' priors were computed incor" +#argv <- list(c(' \036 The other major change was an error for asymmetric loss matrices,', ' prompted by a user query. With L=loss asymmetric, the altered', ' priors were computed incorrectly - they were using L\' instead of L.', ' Upshot - the tree would not not necessarily choose optimal splits', ' for the given loss matrix. Once chosen, splits were evaluated', ' correctly. The printed “improvement” values are of course the', ' wrong ones as well. It is interesting that for my little test', ' case, with L quite asymmetric, the early splits in the tree are', ' unchanged - a good split still looks good.'));nzchar(argv[[1]]); +[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_oldClass.testGetClass +#{ f <- quote(foo(42)); class(f)<-'myclass'; oldClass(f); } +[1] "myclass" ##com.oracle.truffle.r.test.builtins.TestBuiltin_oldClass.testGetClass #{ oldClass(NULL) } @@ -32137,6 +32743,31 @@ Error in Ops.factor(factor(c("a", "b", "c")), factor(c(1, 2, 3))) : [1,] 7 [2,] 9 +##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testNames +#data <- c(1,2,3,4); names(data) <- c('a','b','c','d'); data[c('a','b')] + data[c('c','d')]; data[c('a','b')] + data[c('c')]; data[c('a')] + data[c('c','d')]; data[c('a')] + data[c('c')]; data[c('a')] + 1; 1 + data[c('a')]; data[c('a')] + c(1,2); c(1,2) + data[c('a')]; data[c('a','b')] + 1; 1 + data[c('a','b')]; data[c('a','b')] + c(1,2); c(1,2) + data[c('a','b')] +a b +4 6 +a b +4 5 +c d +4 5 +a +4 +a +2 +a +2 +[1] 2 3 +[1] 2 3 +a b +2 3 +a b +2 3 +a b +2 4 +a b +2 4 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testOperators #as.symbol('asdf') + as.symbol('fdsa') Error in as.symbol("asdf") + as.symbol("fdsa") : @@ -33924,7 +34555,7 @@ NA ##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators203 #argv <- list(structure(1395082079.73982, class = c('POSIXct', 'POSIXt')));`(`(argv[[1]]); -[1] "2014-03-17 19:47:59 CET" +[1] "2014-03-17 18:47:59 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators204 #argv <- list(quote(y ~ a + b:c + d + e + e:d));`(`(argv[[1]]); @@ -34237,7 +34868,7 @@ Frequency = 1 ##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators236 #argv <- list(structure(1395082079.75887, class = c('POSIXct', 'POSIXt')), 3600);`-`(argv[[1]],argv[[2]]); -[1] "2014-03-17 18:47:59 CET" +[1] "2014-03-17 17:47:59 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators237 #argv <- list(structure(c(2, 1, 0, 1, 0, NA, NA, NA, 0), .Dim = c(3L, 3L)), structure(c(1, 1, 1, 0.5, 0.5, 0.5, 0, 0, 0), .Dim = c(3L, 3L)));`-`(argv[[1]],argv[[2]]); @@ -36692,6 +37323,23 @@ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE #argv <- list(150000, 3e+09);`<=`(argv[[1]],argv[[2]]); [1] TRUE +##com.oracle.truffle.r.test.builtins.TestBuiltin_options.testOptions +#{ getOption(NULL) } +Error in getOption(NULL) : 'x' must be a character string + +##com.oracle.truffle.r.test.builtins.TestBuiltin_options.testOptions +#{ getOption(character()) } +Error in getOption(character()) : 'x' must be a character string + +##com.oracle.truffle.r.test.builtins.TestBuiltin_options.testOptions +#{ options("timeout", "width") } +$timeout +[1] 60 + +$width +[1] 80 + + ##com.oracle.truffle.r.test.builtins.TestBuiltin_options.testoptions1 #argv <- list('survfit.print.n'); .Internal(options(argv[[1]])) $survfit.print.n @@ -36728,6 +37376,10 @@ $ts.eps ##com.oracle.truffle.r.test.builtins.TestBuiltin_options.testoptions5 #argv <- list(NULL); .Internal(options(argv[[1]])) +##com.oracle.truffle.r.test.builtins.TestBuiltin_order.testOrder +#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() } NULL @@ -36974,6 +37626,74 @@ foo #argv <- list();do.call('pairlist', argv) NULL +##com.oracle.truffle.r.test.builtins.TestBuiltin_parentenv.testParentEnv +#e <- new.env(); parent.env(e) +<environment: R_GlobalEnv> + +##com.oracle.truffle.r.test.builtins.TestBuiltin_parentenv.testParentEnv +#parent.env() +Error in parent.env() : argument "env" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_parentenv.testParentEnv +#parent.env(1) +Error in parent.env(1) : argument is not an environment + +##com.oracle.truffle.r.test.builtins.TestBuiltin_parentenv.testParentEnv +#parent.env(NULL) +Error in parent.env(NULL) : argument is not an environment + +##com.oracle.truffle.r.test.builtins.TestBuiltin_parentenv.testParentEnv +#parent.env(c(1,2,3)) +Error in parent.env(c(1, 2, 3)) : argument is not an environment + +##com.oracle.truffle.r.test.builtins.TestBuiltin_parentenvassign.testParentEnv +#e <- new.env(); e2 <- new.env(); parent.env(e) <- e2; parent.env(e) +<environment: 0x7fd30086dbc8> + +##com.oracle.truffle.r.test.builtins.TestBuiltin_parentenvassign.testParentEnv +#e <- new.env(); parent.env(e) <- 44 +Error in `parent.env<-`(`*tmp*`, value = 44) : + 'parent' is not an environment + +##com.oracle.truffle.r.test.builtins.TestBuiltin_parentenvassign.testParentEnv +#e <- new.env(); parent.env(e) <- NULL +Error in `parent.env<-`(`*tmp*`, value = NULL) : + use of NULL environment is defunct + +##com.oracle.truffle.r.test.builtins.TestBuiltin_parentenvassign.testParentEnv +#e <- new.env(); parent.env(e) <- c(1,2,3) +Error in `parent.env<-`(`*tmp*`, value = c(1, 2, 3)) : + 'parent' is not an environment + +##com.oracle.truffle.r.test.builtins.TestBuiltin_parentenvassign.testParentEnv +#e <- new.env(); parent.env(e) <- emptyenv(); parent.env(e) +<environment: R_EmptyEnv> + +##com.oracle.truffle.r.test.builtins.TestBuiltin_parentenvassign.testParentEnv +#parent.env() <- new.env() +Error in parent.env() <- new.env() : + invalid (NULL) left side of assignment + +##com.oracle.truffle.r.test.builtins.TestBuiltin_parentenvassign.testParentEnv +#parent.env(1) <- new.env() +Error in parent.env(1) <- new.env() : + target of assignment expands to non-language object + +##com.oracle.truffle.r.test.builtins.TestBuiltin_parentenvassign.testParentEnv +#parent.env(NULL) <- new.env() +Error in parent.env(NULL) <- new.env() : + invalid (NULL) left side of assignment + +##com.oracle.truffle.r.test.builtins.TestBuiltin_parentenvassign.testParentEnv +#parent.env(c(1,2,3)) <- new.env() +Error in parent.env(c(1, 2, 3)) <- new.env() : + target of assignment expands to non-language object + +##com.oracle.truffle.r.test.builtins.TestBuiltin_parentenvassign.testParentEnv +#parent.env(emptyenv()) <- new.env() +Error in parent.env(emptyenv()) <- new.env() : + invalid (NULL) left side of assignment + ##com.oracle.truffle.r.test.builtins.TestBuiltin_parentframe.testParentFrame #parent.frame() <environment: R_GlobalEnv> @@ -37032,6 +37752,10 @@ expression(NULL) #{ typeof(parse(text = "foo", keep.source = FALSE, srcfile = NULL)[[1]]) } [1] "symbol" +##com.oracle.truffle.r.test.builtins.TestBuiltin_parse.testArgumentsCasts +#.Internal(parse(stdin(), c(1,2), c('expr1', 'expr2'), '?', '<weird-text', 'unknown')) +expression(expr1) + ##com.oracle.truffle.r.test.builtins.TestBuiltin_parse.testParseDataFrame #eval(parse(text=deparse(data.frame(x=c(1))))) x @@ -37077,6 +37801,12 @@ expression(somethingthatdoesnotexist) #parse(text=deparse(c(1, 2, 3))) expression(c(1, 2, 3)) +##com.oracle.truffle.r.test.builtins.TestBuiltin_parse.testParseVector +#{ parse(text=c("for (i in 1:10) {", " x[i] <- i", "}")) } +expression(for (i in 1:10) { + x[i] <- i +}) + ##com.oracle.truffle.r.test.builtins.TestBuiltin_parse.testSource #{ source("test/r/simple/data/tree2/setx.r") ; x } Error in file(filename, "r", encoding = encoding) : @@ -37323,6 +38053,14 @@ character(0) #argv <- list(list(), NULL); .Internal(paste0(argv[[1]], argv[[2]])) character(0) +##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 +#path.expand(NULL) +Error in path.expand(NULL) : invalid 'path' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_pathexpand.testpathexpand1 #argv <- list('/tmp/RtmptPgrXI/Pkgs/pkgA'); .Internal(path.expand(argv[[1]])) [1] "/tmp/RtmptPgrXI/Pkgs/pkgA" @@ -37344,6 +38082,28 @@ character(0) #argv <- structure(list(e1 = structure(1, units = 'days', class = 'difftime'), e2 = structure(14579, class = 'Date')), .Names = c('e1', 'e2'));do.call('+.Date', argv) [1] "2009-12-02" +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testArgumentsCasts +#pmatch(1, NULL) +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testArgumentsCasts +#pmatch(1:5, c(1,3), duplicates.ok=42) +[1] 1 NA 2 NA NA + +##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: +In pmatch(1:5, c(1, 3), nomatch = "str") : NAs introduced by coercion + +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testArgumentsCasts +#pmatch(1:5, c(1,3), nomatch=NULL) +[1] 1 NA 2 NA NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testArgumentsCasts +#pmatch(NULL, 1) +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 @@ -37564,6 +38324,22 @@ numeric(0) [22] 42.000001 8.859155 59.952755 7.222226 27.000000 7.295775 6.377954 [29] 2.407407 14.500000 7.295775 10.204727 +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testArgsCasting +#.Internal(pmin(3, quote(a))) +Error: invalid input type + +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testArgsCasting +#pmin(c(1,2), c(3,0), na.rm='asd') +Error in pmin(c(1, 2), c(3, 0), na.rm = "asd") : invalid 'na.rm' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testArgsCasting +#pmin(c(1,2), c(3,0), na.rm=NA) +Error in pmin(c(1, 2), c(3, 0), na.rm = NA) : invalid 'na.rm' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testArgsCasting +#pmin(c(1,2), c(3,NA), na.rm=c(42, 0)) +[1] 1 2 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin #{ pmin(7+42i) } Error in pmin(7 + (0+42i)) : invalid input type @@ -37818,6 +38594,10 @@ $n [1] 1 +##com.oracle.truffle.r.test.builtins.TestBuiltin_primUntrace.testArgsCasts +#.primUntrace(42) +Error in .primUntrace(42) : argument must be a function + ##com.oracle.truffle.r.test.builtins.TestBuiltin_primUntrace.testprimUntrace1 #argv <- list(.Primitive('sum'));.primUntrace(argv[[1]]); @@ -39156,69 +39936,57 @@ x <- x + 1 integer(0) ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange1 -#argv <- list(c(0.0303542455381287, 0.030376780241572, 0.030376780241572, 0.0317964665585001, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0334189652064179, 0.0352217414818821, 0.0354245538128718, 0.0354245538128718, 0.0376780241572021, 0.0376780241572021, 0.0376780241572021, 0.0376780241572021, 0.0406300703082748, 0.0406300703082748, 0.0406300703082748, 0.0440778799351001, 0.048021453037678, 0.0524607896160087, 0.0524607896160087, 0.0524607896160087, 0.0628267531999279, 0.0693167477915991, 0.0981611681990265, 0.134937804218497, 0.179646655850009, 0.437804218496485), na.rm = FALSE);range(argv[[1]],argv[[2]]); -[1] 0.0000000 0.4378042 +#argv <- list(c(0.0303542455381287, 0.030376780241572, 0.030376780241572, 0.0317964665585001, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0334189652064179, 0.0352217414818821, 0.0354245538128718, 0.0354245538128718, 0.0376780241572021, 0.0376780241572021, 0.0376780241572021, 0.0376780241572021, 0.0406300703082748, 0.0406300703082748, 0.0406300703082748, 0.0440778799351001, 0.048021453037678, 0.0524607896160087, 0.0524607896160087, 0.0524607896160087, 0.0628267531999279, 0.0693167477915991, 0.0981611681990265, 0.134937804218497, 0.179646655850009, 0.437804218496485));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] 0.03035425 0.03037678 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange10 -#argv <- list(structure(c(-3.5527136788005e-14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6.21724893790088e-15, -1.77635683940025e-15, -8.88178419700125e-16, -1.33226762955019e-15, -1.22124532708767e-15, -8.88178419700125e-16, -1.33226762955019e-15, -1.22124532708767e-15, -1.33226762955019e-15, -1.11022302462516e-15, -8.88178419700125e-16, -1.33226762955019e-15, -8.88178419700125e-16, -8.88178419700125e-16, -4.44089209850063e-16, -4.44089209850063e-16, -1.22124532708767e-15, -1.22124532708767e-15, -8.88178419700125e-16, -1.33226762955019e-15, -8.88178419700125e-16, -4.44089209850063e-16, -6.66133814775094e-16, -7.7715611723761e-16, -4.44089209850063e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -1.33226762955019e-15, -1.33226762955019e-15, -1.33226762955019e-15, -8.88178419700125e-16, -1.11022302462516e-15, -4.44089209850063e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -1.33226762955019e-15, -1.33226762955019e-15, -8.88178419700125e-16, -4.44089209850063e-16, -1.22124532708767e-15, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -1.33226762955019e-15, -1.22124532708767e-15, 5.91171556152403e-12, -1.59161572810262e-12, 4.54747350886464e-13, 1.02318153949454e-12, 1.13686837721616e-12, 4.54747350886464e-13, 9.09494701772928e-13, 9.09494701772928e-13, 1.02318153949454e-12, 9.09494701772928e-13, 0, 9.09494701772928e-13, 4.54747350886464e-13, 0, 0, 3.41060513164848e-13, 9.66338120633736e-13, 1.19371179607697e-12, 2.27373675443232e-13, 9.66338120633736e-13, 2.27373675443232e-13, 0, 4.54747350886464e-13, 9.66338120633736e-13, 0, 6.82121026329696e-13, 4.54747350886464e-13, 2.27373675443232e-13, 4.54747350886464e-13, 1.08002495835535e-12, 1.02318153949454e-12, 8.5265128291212e-13, 7.38964445190504e-13, 9.09494701772928e-13, 4.54747350886464e-13, 5.6843418860808e-13, 7.105427357601e-13, 3.41060513164848e-13, 0, 0, 9.66338120633736e-13, 1.02318153949454e-12, 0, 4.54747350886464e-13, 1.13686837721616e-12, 1.05160324892495e-12, 9.09494701772928e-13, 3.41060513164848e-13, 8.38440428196918e-13, 1.4210854715202e-12, 1.15463194561016e-14, -8.88178419700125e-16, -1.33226762955019e-15, -2.02615701994091e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 8.88178419700125e-16, 2.22044604925031e-15, 1.77635683940025e-15, 0, 1.33226762955019e-15, 8.88178419700125e-16, 2.22044604925031e-15, 2.22044604925031e-15, 1.77635683940025e-15, 1.77635683940025e-15, 8.88178419700125e-16, 4.44089209850063e-16, 0, 1.77635683940025e-15, 8.88178419700125e-16, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.11022302462516e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.55431223447522e-15, 1.66533453693773e-15, 2.66453525910038e-15, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 1.77635683940025e-15, 2.22044604925031e-15, 8.88178419700125e-16, 2.22044604925031e-15, 3.77475828372553e-15, 1.77635683940025e-15, 0, 1.33226762955019e-15, 0, 2.66453525910038e-15), .Dim = c(50L, 4L), .Dimnames = list(c('Australia', 'Austria', 'Belgium', 'Bolivia', 'Brazil', 'Canada', 'Chile', 'China', 'Colombia', 'Costa Rica', 'Denmark', 'Ecuador', 'Finland', 'France', 'Germany', 'Greece', 'Guatamala', 'Honduras', 'Iceland', 'India', 'Ireland', 'Italy', 'Japan', 'Korea', 'Luxembourg', 'Malta', 'Norway', 'Netherlands', 'New Zealand', 'Nicaragua', 'Panama', 'Paraguay', 'Peru', 'Philippines', 'Portugal', 'South Africa', 'South Rhodesia', 'Spain', 'Sweden', 'Switzerland', 'Turkey', 'Tunisia', 'United Kingdom', 'United States', 'Venezuela', 'Zambia', 'Jamaica', 'Uruguay', 'Libya', 'Malaysia'), c('pop15', 'pop75', 'dpi', 'ddpi'))), na.rm = FALSE);range(argv[[1]],argv[[2]]); -[1] -1.591616e-12 5.911716e-12 +#argv <- list(structure(c(-3.5527136788005e-14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6.21724893790088e-15, -1.77635683940025e-15, -8.88178419700125e-16, -1.33226762955019e-15, -1.22124532708767e-15, -8.88178419700125e-16, -1.33226762955019e-15, -1.22124532708767e-15, -1.33226762955019e-15, -1.11022302462516e-15, -8.88178419700125e-16, -1.33226762955019e-15, -8.88178419700125e-16, -8.88178419700125e-16, -4.44089209850063e-16, -4.44089209850063e-16, -1.22124532708767e-15, -1.22124532708767e-15, -8.88178419700125e-16, -1.33226762955019e-15, -8.88178419700125e-16, -4.44089209850063e-16, -6.66133814775094e-16, -7.7715611723761e-16, -4.44089209850063e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -1.33226762955019e-15, -1.33226762955019e-15, -1.33226762955019e-15, -8.88178419700125e-16, -1.11022302462516e-15, -4.44089209850063e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -1.33226762955019e-15, -1.33226762955019e-15, -8.88178419700125e-16, -4.44089209850063e-16, -1.22124532708767e-15, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -1.33226762955019e-15, -1.22124532708767e-15, 5.91171556152403e-12, -1.59161572810262e-12, 4.54747350886464e-13, 1.02318153949454e-12, 1.13686837721616e-12, 4.54747350886464e-13, 9.09494701772928e-13, 9.09494701772928e-13, 1.02318153949454e-12, 9.09494701772928e-13, 0, 9.09494701772928e-13, 4.54747350886464e-13, 0, 0, 3.41060513164848e-13, 9.66338120633736e-13, 1.19371179607697e-12, 2.27373675443232e-13, 9.66338120633736e-13, 2.27373675443232e-13, 0, 4.54747350886464e-13, 9.66338120633736e-13, 0, 6.82121026329696e-13, 4.54747350886464e-13, 2.27373675443232e-13, 4.54747350886464e-13, 1.08002495835535e-12, 1.02318153949454e-12, 8.5265128291212e-13, 7.38964445190504e-13, 9.09494701772928e-13, 4.54747350886464e-13, 5.6843418860808e-13, 7.105427357601e-13, 3.41060513164848e-13, 0, 0, 9.66338120633736e-13, 1.02318153949454e-12, 0, 4.54747350886464e-13, 1.13686837721616e-12, 1.05160324892495e-12, 9.09494701772928e-13, 3.41060513164848e-13, 8.38440428196918e-13, 1.4210854715202e-12, 1.15463194561016e-14, -8.88178419700125e-16, -1.33226762955019e-15, -2.02615701994091e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 8.88178419700125e-16, 2.22044604925031e-15, 1.77635683940025e-15, 0, 1.33226762955019e-15, 8.88178419700125e-16, 2.22044604925031e-15, 2.22044604925031e-15, 1.77635683940025e-15, 1.77635683940025e-15, 8.88178419700125e-16, 4.44089209850063e-16, 0, 1.77635683940025e-15, 8.88178419700125e-16, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.11022302462516e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.55431223447522e-15, 1.66533453693773e-15, 2.66453525910038e-15, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 1.77635683940025e-15, 2.22044604925031e-15, 8.88178419700125e-16, 2.22044604925031e-15, 3.77475828372553e-15, 1.77635683940025e-15, 0, 1.33226762955019e-15, 0, 2.66453525910038e-15), .Dim = c(50L, 4L), .Dimnames = list(c('Australia', 'Austria', 'Belgium', 'Bolivia', 'Brazil', 'Canada', 'Chile', 'China', 'Colombia', 'Costa Rica', 'Denmark', 'Ecuador', 'Finland', 'France', 'Germany', 'Greece', 'Guatamala', 'Honduras', 'Iceland', 'India', 'Ireland', 'Italy', 'Japan', 'Korea', 'Luxembourg', 'Malta', 'Norway', 'Netherlands', 'New Zealand', 'Nicaragua', 'Panama', 'Paraguay', 'Peru', 'Philippines', 'Portugal', 'South Africa', 'South Rhodesia', 'Spain', 'Sweden', 'Switzerland', 'Turkey', 'Tunisia', 'United Kingdom', 'United States', 'Venezuela', 'Zambia', 'Jamaica', 'Uruguay', 'Libya', 'Malaysia'), c('pop15', 'pop75', 'dpi', 'ddpi'))));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] -3.552714e-14 0.000000e+00 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange11 -#argv <- list(structure(c(4L, 5L, 1L, 5L, 3L, 4L, 5L, 3L, 2L, 4L), .Label = c('a', 'c', 'i', 's', 't'), class = c('ordered', 'factor')), structure(c(4L, 2L, 3L, 5L, 4L, 3L, 5L, 1L, 5L, 4L), .Label = c('a', 'c', 'i', 's', 't'), class = c('ordered', 'factor')), na.rm = FALSE);range(argv[[1]],argv[[2]],argv[[3]]); -Error in Summary.ordered(c(4L, 5L, 1L, 5L, 3L, 4L, 5L, 3L, 2L, 4L), c(4L, : - 'range' is only meaningful for ordered factors if all arguments have the same level sets +#argv <- list(structure(c(4L, 5L, 1L, 5L, 3L, 4L, 5L, 3L, 2L, 4L), .Label = c('a', 'c', 'i', 's', 't'), class = c('ordered', 'factor')), structure(c(4L, 2L, 3L, 5L, 4L, 3L, 5L, 1L, 5L, 4L), .Label = c('a', 'c', 'i', 's', 't'), class = c('ordered', 'factor')));range(argv[[1]][[1]],argv[[1]][[2]],argv[[1]][[3]], na.rm = FALSE); +[1] a t +Levels: a < c < i < s < t ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange12 -#argv <- list(structure(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, 94, 95, 96, 97, 98, 99, 100, 101), .Tsp = c(1, 101, 1), class = 'ts'), na.rm = FALSE);range(argv[[1]],argv[[2]]); -[1] 0 101 +#argv <- list(structure(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, 94, 95, 96, 97, 98, 99, 100, 101), .Tsp = c(1, 101, 1), class = 'ts'));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] 1 2 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange13 -#argv <- list(c(NA, 1, 2, 3, -Inf, NaN, Inf), na.rm = FALSE);range(argv[[1]],argv[[2]]); +#argv <- list(c(NA, 1, 2, 3, -Inf, NaN, Inf));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); [1] NA NA ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange14 -#argv <- list(c(14.43333, 65.7667), finite = TRUE, na.rm = FALSE);range(argv[[1]],argv[[2]],argv[[3]]); -[1] 0.0000 65.7667 +#argv <- list(c(14.43333, 65.7667), finite = TRUE);range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] 14.43333 65.76670 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange15 -#argv <- list(structure(c(1, 13, 31), .Dim = 3L, .Dimnames = list(c('1st', '2nd', '3rd'))), finite = TRUE, na.rm = FALSE);range(argv[[1]],argv[[2]],argv[[3]]); -[1] 0 31 - -##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange16 -#argv <- list(list(), na.rm = TRUE);range(argv[[1]],argv[[2]]); -[1] 1 1 +#argv <- list(structure(c(1, 13, 31), .Dim = 3L, .Dimnames = list(c('1st', '2nd', '3rd'))), finite = TRUE);range(argv[[1]][[1]],argv[[1]][[2]],argv[[1]][[3]], na.rm = FALSE); +[1] 1 31 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange17 -#argv <- list(structure(c(1012633320L, 1012633620L), class = c('POSIXct', 'POSIXt'), tzone = ''), na.rm = TRUE);range(argv[[1]],argv[[2]]); -[1] "1970-01-01 01:00:01 CET" "2002-02-02 08:07:00 CET" - -##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange18 -#argv <- list(structure(numeric(0), .Dim = c(0L, 0L)), na.rm = FALSE);range(argv[[1]],argv[[2]]); -[1] 0 0 - -##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange19 -#argv <- list(structure(logical(0), .Dim = c(0L, 0L), .Dimnames = list(NULL, NULL)), na.rm = FALSE);range(argv[[1]],argv[[2]]); -[1] 0 0 +#argv <- list(structure(c(1012633320L, 1012633620L), class = c('POSIXct', 'POSIXt'), tzone = ''));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE); +[1] "2002-02-02 07:02:00 GMT" "2002-02-02 07:07:00 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange2 -#argv <- list(structure(c(52L, 52L), .Names = c('y', 'x')), na.rm = FALSE);range(argv[[1]],argv[[2]]); -[1] 0 52 +#argv <- list(structure(c(52L, 52L), .Names = c('y', 'x')));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] 52 52 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange20 -#argv <- list(c(2.00256647265648e-308, 2.22284878464869e-308, 2.22507363599982e-308, 2.2250738585072e-308, 2.22507408101459e-308, 2.22729893236571e-308, 2.44758124435792e-308), na.rm = FALSE);range(argv[[1]],argv[[2]]); -[1] 0.000000e+00 2.447581e-308 +#argv <- list(c(2.00256647265648e-308, 2.22284878464869e-308, 2.22507363599982e-308, 2.2250738585072e-308, 2.22507408101459e-308, 2.22729893236571e-308, 2.44758124435792e-308));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] 2.002566e-308 2.222849e-308 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange21 -#argv <- list(structure(c(12053, 12054, 12055, 12056, 12057, 12058, 12059, 12060, 12061, 12062), class = 'Date'), na.rm = TRUE);range(argv[[1]],argv[[2]]); -[1] "1970-01-02" "2003-01-10" +#argv <- list(structure(c(12053, 12054, 12055, 12056, 12057, 12058, 12059, 12060, 12061, 12062), class = 'Date'));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE); +[1] "2003-01-01" "2003-01-02" ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange22 -#argv <- list(structure(c(1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, NA, 1L, 1L, 2L, 1L, 1L, NA, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, NA, 2L, 2L, 1L, NA, 2L, 2L, NA, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 1L), .Dim = c(20L, 6L), .Dimnames = list(c('ant', 'bee', 'cat', 'cpl', 'chi', 'cow', 'duc', 'eag', 'ele', 'fly', 'fro', 'her', 'lio', 'liz', 'lob', 'man', 'rab', 'sal', 'spi', 'wha'), c('war', 'fly', 'ver', 'end', 'gro', 'hai'))), na.rm = TRUE);range(argv[[1]],argv[[2]]); -[1] NA NA +#argv <- list(structure(c(1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, NA, 1L, 1L, 2L, 1L, 1L, NA, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, NA, 2L, 2L, 1L, NA, 2L, 2L, NA, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 1L), .Dim = c(20L, 6L), .Dimnames = list(c('ant', 'bee', 'cat', 'cpl', 'chi', 'cow', 'duc', 'eag', 'ele', 'fly', 'fro', 'her', 'lio', 'liz', 'lob', 'man', 'rab', 'sal', 'spi', 'wha'), c('war', 'fly', 'ver', 'end', 'gro', 'hai'))));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE); +[1] 1 1 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange23 -#argv <- list(structure(c(13823, NA), class = 'Date'), na.rm = TRUE);range(argv[[1]],argv[[2]]); -[1] NA NA +#argv <- list(structure(c(13823, NA), class = 'Date'));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE); +[1] "2007-11-06" "2007-11-06" ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange24 #range( ); @@ -39230,62 +39998,73 @@ Warning messages: no non-missing arguments to max; returning -Inf ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange25 -#argv <- list(structure(c(1949, 1949.08333333333, 1949.16666666667, 1949.25, 1949.33333333333, 1949.41666666667, 1949.5, 1949.58333333333, 1949.66666666667, 1949.75, 1949.83333333333, 1949.91666666667, 1950, 1950.08333333333, 1950.16666666667, 1950.25, 1950.33333333333, 1950.41666666667, 1950.5, 1950.58333333333, 1950.66666666667, 1950.75, 1950.83333333333, 1950.91666666667, 1951, 1951.08333333333, 1951.16666666667, 1951.25, 1951.33333333333, 1951.41666666667, 1951.5, 1951.58333333333, 1951.66666666667, 1951.75, 1951.83333333333, 1951.91666666667, 1952, 1952.08333333333, 1952.16666666667, 1952.25, 1952.33333333333, 1952.41666666667, 1952.5, 1952.58333333333, 1952.66666666667, 1952.75, 1952.83333333333, 1952.91666666667, 1953, 1953.08333333333, 1953.16666666667, 1953.25, 1953.33333333333, 1953.41666666667, 1953.5, 1953.58333333333, 1953.66666666667, 1953.75, 1953.83333333333, 1953.91666666667, 1954, 1954.08333333333, 1954.16666666667, 1954.25, 1954.33333333333, 1954.41666666667, 1954.5, 1954.58333333333, 1954.66666666667, 1954.75, 1954.83333333333, 1954.91666666667, 1955, 1955.08333333333, 1955.16666666667, 1955.25, 1955.33333333333, 1955.41666666667, 1955.5, 1955.58333333333, 1955.66666666667, 1955.75, 1955.83333333333, 1955.91666666667, 1956, 1956.08333333333, 1956.16666666667, 1956.25, 1956.33333333333, 1956.41666666667, 1956.5, 1956.58333333333, 1956.66666666667, 1956.75, 1956.83333333333, 1956.91666666667, 1957, 1957.08333333333, 1957.16666666667, 1957.25, 1957.33333333333, 1957.41666666667, 1957.5, 1957.58333333333, 1957.66666666667, 1957.75, 1957.83333333333, 1957.91666666667, 1958, 1958.08333333333, 1958.16666666667, 1958.25, 1958.33333333333, 1958.41666666667, 1958.5, 1958.58333333333, 1958.66666666667, 1958.75, 1958.83333333333, 1958.91666666667, 1959, 1959.08333333333, 1959.16666666667, 1959.25, 1959.33333333333, 1959.41666666667, 1959.5, 1959.58333333333, 1959.66666666667, 1959.75, 1959.83333333333, 1959.91666666667, 1960, 1960.08333333333, 1960.16666666667, 1960.25, 1960.33333333333, 1960.41666666667, 1960.5, 1960.58333333333, 1960.66666666667, 1960.75, 1960.83333333333, 1960.91666666667, 1961, 1961.08333333333, 1961.16666666667, 1961.25, 1961.33333333333, 1961.41666666667, 1961.5, 1961.58333333333, 1961.66666666667, 1961.75, 1961.83333333333, 1961.91666666667, 1962, 1962.08333333333, 1962.16666666667, 1962.25, 1962.33333333333, 1962.41666666667, 1962.5, 1962.58333333333, 1962.66666666667, 1962.75, 1962.83333333333, 1962.91666666667), .Tsp = c(1949, 1962.91666666667, 12), class = 'ts'), na.rm = FALSE);range(argv[[1]],argv[[2]]); -[1] 0.000 1962.917 +#argv <- list(structure(c(1949, 1949.08333333333, 1949.16666666667, 1949.25, 1949.33333333333, 1949.41666666667, 1949.5, 1949.58333333333, 1949.66666666667, 1949.75, 1949.83333333333, 1949.91666666667, 1950, 1950.08333333333, 1950.16666666667, 1950.25, 1950.33333333333, 1950.41666666667, 1950.5, 1950.58333333333, 1950.66666666667, 1950.75, 1950.83333333333, 1950.91666666667, 1951, 1951.08333333333, 1951.16666666667, 1951.25, 1951.33333333333, 1951.41666666667, 1951.5, 1951.58333333333, 1951.66666666667, 1951.75, 1951.83333333333, 1951.91666666667, 1952, 1952.08333333333, 1952.16666666667, 1952.25, 1952.33333333333, 1952.41666666667, 1952.5, 1952.58333333333, 1952.66666666667, 1952.75, 1952.83333333333, 1952.91666666667, 1953, 1953.08333333333, 1953.16666666667, 1953.25, 1953.33333333333, 1953.41666666667, 1953.5, 1953.58333333333, 1953.66666666667, 1953.75, 1953.83333333333, 1953.91666666667, 1954, 1954.08333333333, 1954.16666666667, 1954.25, 1954.33333333333, 1954.41666666667, 1954.5, 1954.58333333333, 1954.66666666667, 1954.75, 1954.83333333333, 1954.91666666667, 1955, 1955.08333333333, 1955.16666666667, 1955.25, 1955.33333333333, 1955.41666666667, 1955.5, 1955.58333333333, 1955.66666666667, 1955.75, 1955.83333333333, 1955.91666666667, 1956, 1956.08333333333, 1956.16666666667, 1956.25, 1956.33333333333, 1956.41666666667, 1956.5, 1956.58333333333, 1956.66666666667, 1956.75, 1956.83333333333, 1956.91666666667, 1957, 1957.08333333333, 1957.16666666667, 1957.25, 1957.33333333333, 1957.41666666667, 1957.5, 1957.58333333333, 1957.66666666667, 1957.75, 1957.83333333333, 1957.91666666667, 1958, 1958.08333333333, 1958.16666666667, 1958.25, 1958.33333333333, 1958.41666666667, 1958.5, 1958.58333333333, 1958.66666666667, 1958.75, 1958.83333333333, 1958.91666666667, 1959, 1959.08333333333, 1959.16666666667, 1959.25, 1959.33333333333, 1959.41666666667, 1959.5, 1959.58333333333, 1959.66666666667, 1959.75, 1959.83333333333, 1959.91666666667, 1960, 1960.08333333333, 1960.16666666667, 1960.25, 1960.33333333333, 1960.41666666667, 1960.5, 1960.58333333333, 1960.66666666667, 1960.75, 1960.83333333333, 1960.91666666667, 1961, 1961.08333333333, 1961.16666666667, 1961.25, 1961.33333333333, 1961.41666666667, 1961.5, 1961.58333333333, 1961.66666666667, 1961.75, 1961.83333333333, 1961.91666666667, 1962, 1962.08333333333, 1962.16666666667, 1962.25, 1962.33333333333, 1962.41666666667, 1962.5, 1962.58333333333, 1962.66666666667, 1962.75, 1962.83333333333, 1962.91666666667), .Tsp = c(1949, 1962.91666666667, 12), class = 'ts'));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] 1949.000 1949.083 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange26 -#argv <- list(c(1.47191076131574, 0.586694550701453, 0.258706725324317, 0.948371836939988, 0.396080061109718, 0.350912037541581), finite = TRUE, na.rm = FALSE);range(argv[[1]],argv[[2]],argv[[3]]); -[1] 0.000000 1.471911 +#argv <- list(c(1.47191076131574, 0.586694550701453, 0.258706725324317, 0.948371836939988, 0.396080061109718, 0.350912037541581), finite = TRUE);range(argv[[1]][[1]],argv[[1]][[2]],argv[[1]][[3]], na.rm = FALSE); +[1] 0.2587067 1.4719108 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange27 -#argv <- list(structure(c(-11.3814849918875, -11.9361690778798, 0.562602893455921, 11.5126028934559, 76.2209544348296, -8.66448499188751, -6.94502893455923, -5.28148499188751, -35.7665182531098, 6.35497106544077, -9.20908119253651, -0.898484991887508, -5.59380090589508, -6.12730922120065, -13.3061334505138, 58.6278831800973, -15.1098009058951, -8.29625696322337, -4.07211681990265, 3.7096551514332, 2.60151500811249, 6.24733923742563, -1.33911681990266, -2.14157287723094, -10.5984849918875, -8.12802893455923, 1.30028697944835, -15.7450289345592, 7.20569077879935, -12.6484849918875, 25.1810423201731, -4.42680090589508, -1.90886979448351), .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')), na.rm = TRUE);range(argv[[1]],argv[[2]]); -[1] -35.76652 76.22095 +#argv <- list(structure(c(-11.3814849918875, -11.9361690778798, 0.562602893455921, 11.5126028934559, 76.2209544348296, -8.66448499188751, -6.94502893455923, -5.28148499188751, -35.7665182531098, 6.35497106544077, -9.20908119253651, -0.898484991887508, -5.59380090589508, -6.12730922120065, -13.3061334505138, 58.6278831800973, -15.1098009058951, -8.29625696322337, -4.07211681990265, 3.7096551514332, 2.60151500811249, 6.24733923742563, -1.33911681990266, -2.14157287723094, -10.5984849918875, -8.12802893455923, 1.30028697944835, -15.7450289345592, 7.20569077879935, -12.6484849918875, 25.1810423201731, -4.42680090589508, -1.90886979448351), .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')));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE); +[1] -11.93617 -11.38148 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange28 -#argv <- list(c(9.5367431640625e-07, 1.9073486328125e-06, 3.814697265625e-06, 7.62939453125e-06, 1.52587890625e-05, 3.0517578125e-05, 6.103515625e-05, 0.0001220703125, 0.000244140625, 0.00048828125, 0.0009765625, 0.001953125, 0.00390625, 0.0078125, 0.015625, 0.03125, 0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024), na.rm = FALSE);range(argv[[1]],argv[[2]]); -[1] 0 1024 +#argv <- list(c(9.5367431640625e-07, 1.9073486328125e-06, 3.814697265625e-06, 7.62939453125e-06, 1.52587890625e-05, 3.0517578125e-05, 6.103515625e-05, 0.0001220703125, 0.000244140625, 0.00048828125, 0.0009765625, 0.001953125, 0.00390625, 0.0078125, 0.015625, 0.03125, 0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] 9.536743e-07 1.907349e-06 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange29 -#argv <- list(structure(c(1208822400, 1209168000, 1208822400, 1209168000), class = c('POSIXct', 'POSIXt'), tzone = 'GMT'), na.rm = TRUE);range(argv[[1]],argv[[2]]); -[1] "1970-01-01 00:00:01 GMT" "2008-04-26 00:00:00 GMT" +#argv <- list(structure(c(1208822400, 1209168000, 1208822400, 1209168000), class = c('POSIXct', 'POSIXt'), tzone = 'GMT'));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE); +[1] "2008-04-22 GMT" "2008-04-26 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange3 -#argv <- list(c(-2.92498527625946, 2.46253591019012), na.rm = FALSE);range(argv[[1]],argv[[2]]); +#argv <- list(c(-2.92498527625946, 2.46253591019012));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); [1] -2.924985 2.462536 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange30 -#argv <- list(c(1.86606598307361, 339033474310168, 6.15968019059533e+28, 1.11911250438065e+43, 2.03324321833028e+57, 3.69406826275609e+71, 6.71151400229846e+85, 1.21937162496937e+100, 2.2153975381282e+114, 4.02501267984465e+128, 7.31278553581751e+142, 1.32861276588395e+157, 2.41387071044804e+171, 4.38560576593759e+185, 7.96792382084694e+199, 1.44764060891943e+214, 2.63012470966353e+228, 4.77850368783602e+242, 8.6817546752692e+256, 1.57733192575377e+271), na.rm = FALSE);range(argv[[1]],argv[[2]]); -[1] 0.000000e+00 1.577332e+271 +#argv <- list(c(1.86606598307361, 339033474310168, 6.15968019059533e+28, 1.11911250438065e+43, 2.03324321833028e+57, 3.69406826275609e+71, 6.71151400229846e+85, 1.21937162496937e+100, 2.2153975381282e+114, 4.02501267984465e+128, 7.31278553581751e+142, 1.32861276588395e+157, 2.41387071044804e+171, 4.38560576593759e+185, 7.96792382084694e+199, 1.44764060891943e+214, 2.63012470966353e+228, 4.77850368783602e+242, 8.6817546752692e+256, 1.57733192575377e+271));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] 1.866066e+00 3.390335e+14 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange31 -#argv <- list(structure(c(1, 0.666666666666667, 0.333333333333333, 0, -0.333333333333333, -0.666666666666667, -1, -1.33333333333333, -1.66666666666667, 1.5, 1, 0.5, 0, -0.5, -1, -1.5, -2, -2.5, 3, 2, 1, 0, -1, -2, -3, -4, -5, -Inf, -Inf, -Inf, NaN, Inf, Inf, Inf, Inf, Inf, -3, -2, -1, 0, 1, 2, 3, 4, 5, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, -1, -0.666666666666667, -0.333333333333333, 0, 0.333333333333333, 0.666666666666667, 1, 1.33333333333333, 1.66666666666667, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1, 1.25, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1), .Dim = c(9L, 9L)), na.rm = TRUE);range(argv[[1]],argv[[2]]); -[1] NaN NaN +#argv <- list(structure(c(1, 0.666666666666667, 0.333333333333333, 0, -0.333333333333333, -0.666666666666667, -1, -1.33333333333333, -1.66666666666667, 1.5, 1, 0.5, 0, -0.5, -1, -1.5, -2, -2.5, 3, 2, 1, 0, -1, -2, -3, -4, -5, -Inf, -Inf, -Inf, NaN, Inf, Inf, Inf, Inf, Inf, -3, -2, -1, 0, 1, 2, 3, 4, 5, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, -1, -0.666666666666667, -0.333333333333333, 0, 0.333333333333333, 0.666666666666667, 1, 1.33333333333333, 1.66666666666667, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1, 1.25, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1), .Dim = c(9L, 9L)));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE); +[1] 0.6666667 1.0000000 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange4 -#argv <- list(c(1.4615016373309e+48, 5.70899077082384e+45, 2.23007451985306e+43, 8.71122859317602e+40, 3.40282366920938e+38, 1.32922799578492e+36, 5.19229685853483e+33, 2.02824096036517e+31, 7.92281625142643e+28, 3.09485009821345e+26, 1.20892581961463e+24, 4.72236648286965e+21, 18446744073709551616, 72057594037927936, 281474976710656, 1099511627776, 4294967296, 16777216, 65536, 256, 1, 0.00390625, 1.52587890625e-05, 5.96046447753906e-08, 2.3283064365387e-10, 9.09494701772928e-13, 3.5527136788005e-15, 1.38777878078145e-17, 5.42101086242752e-20, 2.11758236813575e-22, 8.27180612553028e-25), na.rm = FALSE);range(argv[[1]],argv[[2]]); -[1] 0.000000e+00 1.461502e+48 +#argv <- list(c(1.4615016373309e+48, 5.70899077082384e+45, 2.23007451985306e+43, 8.71122859317602e+40, 3.40282366920938e+38, 1.32922799578492e+36, 5.19229685853483e+33, 2.02824096036517e+31, 7.92281625142643e+28, 3.09485009821345e+26, 1.20892581961463e+24, 4.72236648286965e+21, 18446744073709551616, 72057594037927936, 281474976710656, 1099511627776, 4294967296, 16777216, 65536, 256, 1, 0.00390625, 1.52587890625e-05, 5.96046447753906e-08, 2.3283064365387e-10, 9.09494701772928e-13, 3.5527136788005e-15, 1.38777878078145e-17, 5.42101086242752e-20, 2.11758236813575e-22, 8.27180612553028e-25));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] 5.708991e+45 1.461502e+48 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange5 -#argv <- list(1:3, finite = TRUE, na.rm = FALSE);range(argv[[1]],argv[[2]],argv[[3]]); -[1] 0 3 +#argv <- list(1:3, finite = TRUE);range(argv[[1]][[1]],argv[[1]][[2]],argv[[1]][[3]], na.rm = FALSE); +[1] 1 3 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange6 -#argv <- list(c(1L, 3L, 7L, 14L, 21L, 20L, 19L, 9L, 4L, 2L), 0, na.rm = FALSE);range(argv[[1]],argv[[2]],argv[[3]]); -[1] 0 21 +#argv <- list(c(1L, 3L, 7L, 14L, 21L, 20L, 19L, 9L, 4L, 2L), 0);range(argv[[1]][[1]],argv[[1]][[2]],argv[[1]][[3]], na.rm = FALSE); +[1] 1 7 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange7 -#argv <- list(c(8.2, 9.7, 12.25, 16.5, 21.5, 14.5, 20, 23.45, 25.8, 27.3, 22.4, 24.5, 25.95, 27.3, 30.9), numeric(0), NULL, na.rm = FALSE);range(argv[[1]],argv[[2]],argv[[3]],argv[[4]]); -[1] 0.0 30.9 +#argv <- list(c(8.2, 9.7, 12.25, 16.5, 21.5, 14.5, 20, 23.45, 25.8, 27.3, 22.4, 24.5, 25.95, 27.3, 30.9), numeric(0), NULL);range(argv[[1]][[1]],argv[[1]][[2]],argv[[1]][[3]],argv[[1]][[4]], na.rm = FALSE); +[1] 8.2 16.5 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange8 -#argv <- list(structure(c(3L, 2L, 1L), .Label = c('A', 'B', 'C'), class = c('ordered', 'factor')), na.rm = FALSE);range(argv[[1]],argv[[2]]); -Error in Summary.ordered(c(3L, 2L, 1L), FALSE, na.rm = FALSE) : - 'range' is only meaningful for ordered factors if all arguments have the same level sets +#argv <- list(structure(c(3L, 2L, 1L), .Label = c('A', 'B', 'C'), class = c('ordered', 'factor')));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] B C +Levels: A < B < C ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange9 -#argv <- list(structure(list(sec = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), min = c(40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L), hour = c(8L, 8L, 9L, 9L, 9L, 9L, 9L, 9L, 10L, 10L, 10L, 10L, 10L, 10L, 11L, 11L, 11L, 11L, 11L, 11L, 12L, 12L, 12L, 12L, 12L, 12L, 13L, 13L, 13L, 13L, 13L, 13L, 14L, 14L, 14L, 14L, 14L, 14L, 15L, 15L, 15L, 15L, 15L, 15L, 16L, 16L, 16L, 16L, 16L, 16L, 17L, 17L, 17L, 17L, 17L, 17L, 18L, 18L, 18L, 18L, 18L, 18L, 19L, 19L, 19L, 19L, 19L, 19L, 20L, 20L, 20L, 20L, 20L, 20L, 21L, 21L, 21L, 21L, 21L, 21L, 22L, 22L, 22L, 22L, 22L, 23L, 23L, 23L, 23L, 23L, 23L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L), mday = c(12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L), mon = c(11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L), year = c(90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L), wday = c(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, 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, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L), yday = c(345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L), isdst = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L)), .Names = c('sec', 'min', 'hour', 'mday', 'mon', 'year', 'wday', 'yday', 'isdst'), class = c('POSIXlt', 'POSIXt')), na.rm = FALSE);range(argv[[1]],argv[[2]]); -Error in as.POSIXct.default(X[[i]], ...) : - do not know how to convert 'X[[i]]' to class “POSIXct” +#argv <- list(structure(list(sec = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), min = c(40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L), hour = c(8L, 8L, 9L, 9L, 9L, 9L, 9L, 9L, 10L, 10L, 10L, 10L, 10L, 10L, 11L, 11L, 11L, 11L, 11L, 11L, 12L, 12L, 12L, 12L, 12L, 12L, 13L, 13L, 13L, 13L, 13L, 13L, 14L, 14L, 14L, 14L, 14L, 14L, 15L, 15L, 15L, 15L, 15L, 15L, 16L, 16L, 16L, 16L, 16L, 16L, 17L, 17L, 17L, 17L, 17L, 17L, 18L, 18L, 18L, 18L, 18L, 18L, 19L, 19L, 19L, 19L, 19L, 19L, 20L, 20L, 20L, 20L, 20L, 20L, 21L, 21L, 21L, 21L, 21L, 21L, 22L, 22L, 22L, 22L, 22L, 23L, 23L, 23L, 23L, 23L, 23L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L), mday = c(12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L), mon = c(11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L), year = c(90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L), wday = c(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, 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, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L), yday = c(345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L), isdst = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L)), .Names = c('sec', 'min', 'hour', 'mday', 'mon', 'year', 'wday', 'yday', 'isdst'), class = c('POSIXlt', 'POSIXt')));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE); +[1] 0 50 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rank.testArgsCasts +#.Internal(rank(as.raw(42), 42L, 'max')) +Error: raw vectors cannot be sorted + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rank.testArgsCasts +#.Internal(rank(c(1,2), -3L, 'max')) +Error: invalid 'length(xx)' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rank.testArgsCasts +#.Internal(rank(c(1,2), 2L, 'something')) +Error: invalid ties.method for rank() [should never happen] ##com.oracle.truffle.r.test.builtins.TestBuiltin_rank.testRank #{ rank(c(10,100,100,1000)) } @@ -39719,6 +40498,12 @@ z 8 9 b c v 1 2 +##com.oracle.truffle.r.test.builtins.TestBuiltin_rbind.testRbind +#{ x<-data.frame(c(1,2),c(3,4)); dimnames(x) <- list(c("A", "B"), c("C", "D")); rbind(x) } + C D +A 1 3 +B 2 4 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_rbind.testRbind #{ x<-list(a=7, b=NULL, c=42); y<-as.data.frame(do.call(rbind,x)); y } V1 @@ -40048,6 +40833,26 @@ attr(,"match.length") attr(,"useBytes") [1] TRUE +##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testRegExpr +#{ .Internal(regexpr("7", 42, F, F, F, F)) } +Error: invalid 'text' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testRegExpr +#{ .Internal(regexpr(7, "42", F, F, F, F)) } +Error: invalid 'pattern' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testRegExpr +#{ .Internal(regexpr(character(), "42", F, F, F, F)) } +Error: invalid 'pattern' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testRegExpr +#{ as.integer(regexpr("foo", c("bar foo foo", "foo"), fixed=F)) } +[1] 5 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testRegExpr +#{ as.integer(regexpr("foo", c("bar foo foo", "foo"), fixed=T)) } +[1] 5 1 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testRegExpr #{ regexpr("aaa", "bbbaaaccc", fixed=TRUE) } [1] 4 @@ -40088,6 +40893,14 @@ attr(,"useBytes") #{ x<-regexpr("aaa", c("bbbaaaccc", "hah"), fixed=TRUE); c(x[1], x[2]) } [1] 4 -1 +##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testRegExpr +#{ x<-regexpr("foo", c("bar foo foo", "foo")); attr(x, "match.length") } +[1] 3 3 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testRegExpr +#{ x<-regexpr("foo", c("bar foo foo", "foo"), fixed=T); attr(x, "match.length") } +[1] 3 3 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testregexpr1 #argv <- list('package:', 'exNSS4', FALSE, FALSE, TRUE, FALSE); .Internal(regexpr(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]])) [1] -1 @@ -40218,6 +41031,86 @@ attr(,"useBytes") #{ rep(1:3,2) } [1] 1 2 3 1 2 3 +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(7, each="7") } +[1] 7 7 7 7 7 7 7 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(7, each=NA) } +[1] 7 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(7, each=NULL) } +[1] 7 +Warning message: +In rep(7, each = NULL) : first element used of 'each' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(7, each=c(7, 42)) } +[1] 7 7 7 7 7 7 7 +Warning message: +In rep(7, each = c(7, 42)) : first element used of 'each' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(7, each=integer()) } +[1] 7 +Warning message: +In rep(7, each = integer()) : first element used of 'each' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(7, length.out="7") } +[1] 7 7 7 7 7 7 7 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(7, length.out=NA) } +[1] 7 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(7, length.out=NULL) } +[1] 7 +Warning message: +In rep(7, length.out = NULL) : first element used of 'length.out' argument + +##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 +#{ rep(7, length.out=integer()) } +[1] 7 +Warning message: +In rep(7, length.out = integer()) : + first element used of 'length.out' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(7, times="7") } +[1] 7 7 7 7 7 7 7 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(7, times="foo") } +Error in rep(7, times = "foo") : invalid 'times' argument +In addition: Warning message: +NAs introduced by coercion + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(7, times=-1) } +Error in rep(7, times = -1) : invalid 'times' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(7, times=NA) } +Error in rep(7, times = NA) : invalid 'times' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(7, times=NULL) } +Error in rep(7, times = NULL) : invalid 'times' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(7, times=character()) } +Error in rep(7, times = character()) : invalid 'times' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep #{ rep(NA,8) } [1] NA NA NA NA NA NA NA NA @@ -40267,6 +41160,15 @@ numeric(0) #{ rep(c(1,2),c(3,3)) } [1] 1 1 1 2 2 2 +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(c(7, 42), times=c(2, NA)) } +Error in rep(c(7, 42), times = c(2, NA)) : invalid 'times' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep +#{ rep(function() 42) } +Error in rep(function() 42) : + attempt to replicate an object of type 'closure' + ##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep #{ x <- 1 ; names(x) <- c("X") ; rep(x, times=0) } named numeric(0) @@ -40597,6 +41499,26 @@ Levels: A B C D #{ rep_len(3.14159, 3) } [1] 3.14159 3.14159 3.14159 +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep_len.testRepLen +#{ rep_len(7, "7") } +[1] 7 7 7 7 7 7 7 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep_len.testRepLen +#{ rep_len(7, NA) } +Error in rep_len(7, NA) : invalid 'length.out' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep_len.testRepLen +#{ rep_len(7, NULL) } +Error in rep_len(7, NULL) : invalid 'length.out' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep_len.testRepLen +#{ rep_len(7, c(7, 42)) } +Error in rep_len(7, c(7, 42)) : invalid 'length.out' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep_len.testRepLen +#{ rep_len(7, integer()) } +Error in rep_len(7, integer()) : invalid 'length.out' value + ##com.oracle.truffle.r.test.builtins.TestBuiltin_rep_len.testRepLen #{ rep_len(TRUE, 2) } [1] TRUE TRUE @@ -40609,6 +41531,10 @@ Levels: A B C D #{ rep_len(c(3.1415, 0.8), 1) } [1] 3.1415 +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep_len.testRepLen +#{ rep_len(function() 42, 7) } +Error in rep_len(function() 42, 7) : attempt to replicate non-vector + ##com.oracle.truffle.r.test.builtins.TestBuiltin_rep_len.testRepLen #{ x<-as.raw(16); rep_len(x, 2) } [1] 10 10 @@ -40682,6 +41608,26 @@ character(0) #{ rep.int(1L,3L) } [1] 1 1 1 +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt +#{ rep.int(7, "7") } +[1] 7 7 7 7 7 7 7 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt +#{ rep.int(7, NA) } +Error in rep.int(7, NA) : invalid 'times' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt +#{ rep.int(7, NULL) } +Error in rep.int(7, NULL) : incorrect type for second argument + +##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 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt +#{ rep.int(7, character()) } +Error in rep.int(7, character()) : invalid 'times' value + ##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt #{ rep.int(as.raw(14), 4) } [1] 0e 0e 0e 0e @@ -40702,10 +41648,19 @@ 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(function() 42, 7) } +Error in rep.int(function() 42, 7) : + attempt to replicate an object of type 'closure' + ##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt #{ rep.int(seq_len(2), rep.int(8, 2)) } [1] 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt +#{ rep_int(7, function() 42) } +Error: could not find function "rep_int" + ##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 @@ -40930,6 +41885,38 @@ 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_rm.basicTests +# e <- new.env(); e$a <- 42; rm(list='a', envir=e); e$a +NULL + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rm.basicTests +#tmp <- 42; f <- function() rm(list='tmp',inherits=T); f(); tmp +Error: object 'tmp' not found + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rm.basicTests +#tmp <- 42; rm(list='tmp'); tmp +Error: object 'tmp' not found + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rm.basicTests +#tmp <- 42; rm(tmp); tmp +Error: object 'tmp' not found + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rm.testArgsCasting +#.Internal(remove(list=33, environment(), F)) +Error: invalid first argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rm.testArgsCasting +#tmp <- 42; rm(tmp, envir=42) +Error in rm(tmp, envir = 42) : invalid 'envir' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rm.testArgsCasting +#tmp <- 42; rm(tmp, envir=NULL) +Error in rm(tmp, envir = NULL) : use of NULL environment is defunct + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rm.testArgsCasting +#tmp <- 42; rm(tmp, inherits='asd') +Error in rm(tmp, inherits = "asd") : invalid 'inherits' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_round.testRound #{ round(-1.5) } [1] -2 @@ -41017,6 +42004,10 @@ logical(0) 18 0.138 0.758 0.141 0.761 19 0.122 0.775 0.124 0.777 +##com.oracle.truffle.r.test.builtins.TestBuiltin_row.testArgsCasts +#.Internal(row('str')) +Error: a matrix-like object is required as argument to 'row' + ##com.oracle.truffle.r.test.builtins.TestBuiltin_row.testrow1 #argv <- list(c(14L, 14L)); .Internal(row(argv[[1]])) [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] @@ -41126,6 +42117,10 @@ Error in matrix(NA, NA, NA) : invalid 'nrow' value (too large or NA) #{rowMeans(matrix(c(NA,NaN,NaN,NA),ncol=2,nrow=2))} [1] NA NaN +##com.oracle.truffle.r.test.builtins.TestBuiltin_rowMeans.testRowMeans +#{rowMeans(matrix(c(NaN,4+5i,2+0i,5+10i),nrow=2,ncol=2), na.rm = FALSE)} +[1] NA 4.5+7.5i + ##com.oracle.truffle.r.test.builtins.TestBuiltin_rowMeans.testRowMeans #{rowMeans(matrix(c(NaN,4+5i,2+0i,5+10i),nrow=2,ncol=2), na.rm = TRUE)} [1] 2.0+0.0i 4.5+7.5i @@ -41482,6 +42477,83 @@ Y 4 10 16 22 #argv <- structure(list(x = character(0)), .Names = 'x');do.call('sQuote', argv) character(0) +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts +#set.seed(42); .Internal(sample(1/0, 1, FALSE, NULL)) +Error: invalid first argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts +#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 +#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(NaN, NaN, FALSE, NULL)) +Error: vector size cannot be NA/NaN + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts +#set.seed(42); sample(-1) +[1] -1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts +#set.seed(42); sample(0, 0) +numeric(0) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts +#set.seed(42); sample(2, 0) +integer(0) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts +#set.seed(42); sample(3, '2') +[1] 3 2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts +#set.seed(42); sample(3, -3) +Error in sample.int(x, size, replace, prob) : invalid 'size' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts +#set.seed(42); sample(3, 2.0) +[1] 3 2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts +#set.seed(42); sample(3, NA) +Error in sample.int(x, size, replace, prob) : invalid 'size' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts +#set.seed(42); sample(3, TRUE) +Error in sample.int(x, size, replace, prob) : invalid 'size' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts +#set.seed(42); sample(3, c(2,3)) +[1] 3 2 + +##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 +#set.seed(42); sample(4, prob=c(1,2)) +Error in sample.int(x, size, replace, prob) : + incorrect number of probabilities + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts +#set.seed(42); sample(4, replace='s') +Error in !replace : invalid argument type + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts +#set.seed(42); sample(4, replace=1) +[1] 4 4 2 4 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts +#set.seed(42); sample(4, replace=1.2) +[1] 4 4 2 4 + +##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 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testSample #{ set.seed(4357, "default"); x <- 5 ; sample(x, 5, FALSE, NULL) ;} [1] 3 4 5 2 1 @@ -42706,6 +43778,17 @@ integer(0) #argv <- list(list(c(1+1i, 2+1.4142135623731i, 3+1.73205080756888i, 4+2i, 5+2.23606797749979i, 6+2.44948974278318i, 7+2.64575131106459i, 8+2.82842712474619i, 9+3i, 10+3.1622776601684i)));seq_along(argv[[1]]); [1] 1 +##com.oracle.truffle.r.test.builtins.TestBuiltin_seq_len.testSeqLen +#{ seq_len("foo") } +Error in seq_len("foo") : + argument must be coercible to non-negative integer +In addition: Warning message: +NAs introduced by coercion + +##com.oracle.truffle.r.test.builtins.TestBuiltin_seq_len.testSeqLen +#{ seq_len(-1) } +Error in seq_len(-1) : argument must be coercible to non-negative integer + ##com.oracle.truffle.r.test.builtins.TestBuiltin_seq_len.testSeqLen #{ seq_len(10) } [1] 1 2 3 4 5 6 7 8 9 10 @@ -42720,6 +43803,17 @@ In seq_len(1:2) : first element used of 'length.out' argument #{ seq_len(5L) } [1] 1 2 3 4 5 +##com.oracle.truffle.r.test.builtins.TestBuiltin_seq_len.testSeqLen +#{ seq_len(NA) } +Error in seq_len(NA) : argument must be coercible to non-negative integer + +##com.oracle.truffle.r.test.builtins.TestBuiltin_seq_len.testSeqLen +#{ seq_len(NULL) } +Error in seq_len(NULL) : + argument must be coercible to non-negative integer +In addition: Warning message: +In seq_len(NULL) : first element used of 'length.out' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_seq_len.testSeqLen #{ seq_len(integer()) } Error in seq_len(integer()) : @@ -43259,8 +44353,8 @@ Error in seq.int(argv[[1]], argv[[2]], argv[[3]]) : [1] "abc" ##com.oracle.truffle.r.test.builtins.TestBuiltin_setEncoding.testsetEncoding2 -#argv <- list(''', 'unknown'); .Internal(setEncoding(argv[[1]], argv[[2]])) -Error: unexpected string constant in "argv <- list(''', '" +#argv <- list('', 'unknown'); .Internal(setEncoding(argv[[1]], argv[[2]])) +[1] "" ##com.oracle.truffle.r.test.builtins.TestBuiltin_setEncoding.testsetEncoding3 #argv <- list('3.0.1', 'unknown'); .Internal(setEncoding(argv[[1]], argv[[2]])) @@ -43324,6 +44418,30 @@ Error: unexpected string constant in "argv <- list(''', '" ##com.oracle.truffle.r.test.builtins.TestBuiltin_setHook.testsetHook1 #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(x, "TRUE") } +[1] 42 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testSetS4Object +#{ x<-42; asS4(x, TRUE, "1") } +[1] 42 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testSetS4Object +#{ x<-42; asS4(x, TRUE, c(1,2)) } +[1] 42 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testSetS4Object +#{ x<-42; asS4(x, TRUE, logical()) } +Error in asS4(x, TRUE, logical()) : invalid 'complete' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testSetS4Object +#{ x<-42; asS4(x, c(TRUE, FALSE)) } +Error in asS4(x, c(TRUE, FALSE)) : invalid 'flag' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testSetS4Object +#{ x<-42; asS4(x, logical()) } +Error in asS4(x, logical()) : invalid 'flag' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object1 #argv <- list(structure('ObjectsWithPackage', class = structure('signature', package = 'methods'), .Names = '.Object', package = 'methods'), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]])) An object of class “signature” @@ -43521,6 +44639,15 @@ Error: unexpected symbol in "argv <- list('Error in cor(rnorm(10), NULL) : \n s ##com.oracle.truffle.r.test.builtins.TestBuiltin_seterrmessage.testseterrmessage3 #argv <- list('Error in validObject(.Object) : \n invalid class “trackCurve” object: Unequal x,y lengths: 20, 10\n'); .Internal(seterrmessage(argv[[1]])) +##com.oracle.truffle.r.test.builtins.TestBuiltin_setseed.testArgCasts +#set.seed('hello world') +Error in set.seed("hello world") : supplied seed is not a valid integer +In addition: Warning message: +In set.seed("hello world") : NAs introduced by coercion + +##com.oracle.truffle.r.test.builtins.TestBuiltin_setseed.testArgCasts +#set.seed(FALSE) + ##com.oracle.truffle.r.test.builtins.TestBuiltin_setseed.testsetseed1 #argv <- list(1000, 0L, NULL); .Internal(set.seed(argv[[1]], argv[[2]], argv[[3]])) @@ -43549,6 +44676,14 @@ Error: unexpected symbol in "argv <- list('Error in cor(rnorm(10), NULL) : \n s #argv <- structure(list(string = c('ABC', '\'123\'', 'a'b'), type = 'cmd'), .Names = c('string', 'type'));do.call('shQuote', argv) Error: unexpected symbol in "argv <- structure(list(string = c('ABC', '\'123\'', 'a'b" +##com.oracle.truffle.r.test.builtins.TestBuiltin_shortRowNames.testArgCasts +#.Internal(shortRowNames(42, '1')) +[1] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_shortRowNames.testArgCasts +#.Internal(shortRowNames(42, -2)) +Error: invalid 'type' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_shortRowNames.testshortRowNames1 #argv <- list(structure(list(c(8.44399377410362, 28.4640218366572, 12.2441566485997)), row.names = c(NA, -3L), class = 'data.frame'), 1L); .Internal(shortRowNames(argv[[1]], argv[[2]])) [1] -3 @@ -43682,6 +44817,10 @@ integer(0) #argv <- list(numeric(0));sign(argv[[1]]); numeric(0) +##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif +#{ signif("42.1234", 2 } +Error: unexpected '}' in "{ signif("42.1234", 2 }" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif #{ signif(0.0005551, 2) } [1] 0.00056 @@ -43706,6 +44845,59 @@ numeric(0) #{ signif(0.5551, 2) } [1] 0.56 +##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif +#{ signif(42.1234, "2") } +Error in signif(42.1234, "2") : + non-numeric argument to mathematical function + +##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif +#{ signif(42.1234, 1:2) } +[1] 40 42 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif +#{ signif(42.1234, 42+7i) } +Error in signif(42.1234, 42 + (0+7i)) : + non-numeric argument to mathematical function + +##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif +#{ signif(42.1234, as.raw(2)) } +Error in signif(42.1234, as.raw(2)) : + non-numeric argument to mathematical function + +##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif +#{ signif(42.1234, character()) } +Error in signif(42.1234, character()) : + invalid second argument of length 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif +#{ signif(42.1234, matrix(1:2, nrow=1)) } + [,1] [,2] +[1,] 40 42 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif +#{ signif(c(42.1234, 7.1234), 1) } +[1] 40 7 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif +#{ signif(c(42.1234, 7.1234), 1:2) } +[1] 40.0 7.1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif +#{ signif(c(42.1234, 7.1234, 42.1234), c(1,2) } +Error: unexpected '}' in "{ signif(c(42.1234, 7.1234, 42.1234), c(1,2) }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif +#{ x<-42.1234; attr(x, "foo")<-"foo"; signif(x, 2) } +[1] 42 +attr(,"foo") +[1] "foo" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif +#{ x<-FALSE; attr(x, "foo")<-"foo"; signif(x, 2) } +[1] 0 +attr(,"foo") +[1] "foo" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testsignif1 #argv <- list(structure(c(0, NaN, 0, 4.94065645841247e-324), class = 'integer64'));do.call('signif', argv) [1] 0.000000e+00 NaN 0.000000e+00 4.940656e-324 @@ -43941,7 +45133,7 @@ In sin(argv[[1]]) : NaNs produced [100] -0.4571813-1.4592171i ##com.oracle.truffle.r.test.builtins.TestBuiltin_sink.testsink1 -#argv <- list(structure(2L, class = c('terminal', 'connection')), FALSE, TRUE, FALSE); .Internal(sink(argv[[1]], argv[[2]], argv[[3]], argv[[4]])) +#argv <- list(structure(2L, class = c('terminal', 'connection')), FALSE, FALSE, FALSE); .Internal(sink(argv[[1]], argv[[2]], argv[[3]], argv[[4]])) ##com.oracle.truffle.r.test.builtins.TestBuiltin_sink.testsink3 #argv <- list(-1L, FALSE, FALSE, FALSE); .Internal(sink(argv[[1]], argv[[2]], argv[[3]], argv[[4]])) @@ -44067,6 +45259,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(c(1L,10L,2L), 'not-numeric')) } +Error: 'decreasing' must be TRUE or FALSE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testArgsCasts +#{ .Internal(sort(c(1L,10L,2L), NULL)) } +Error: 'decreasing' must be TRUE or FALSE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testSort #{ sort(3:1, index.return=TRUE) } $x @@ -45604,36 +46804,36 @@ B FALSE TRUE ##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 CEST" +[1] "2008-04-22 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.teststrptime10 #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]])) - [1] "1937-01-01 CET" "1916-01-01 CET" "1913-01-01 CET" "1927-01-01 CET" - [5] "1947-01-01 CET" "1913-01-01 CET" "1917-01-01 CET" "1923-01-01 CET" - [9] "1921-01-01 CET" "1926-01-01 CET" "1920-01-01 CET" "1915-01-01 CET" - [13] "1914-01-01 CET" "1914-01-01 CET" "1914-01-01 CET" "1919-01-01 CET" - [17] "1948-01-01 CET" "1911-01-01 CET" "1909-01-01 CET" "1913-01-01 CET" - [21] "1925-01-01 CET" "1926-01-01 CET" "1910-01-01 CET" "1917-01-01 CET" - [25] "1936-01-01 CET" "1938-01-01 CET" "1960-01-01 CET" "1915-01-01 CET" - [29] "1919-01-01 CET" "1924-01-01 CET" "1914-01-01 CET" "1905-01-01 CET" - [33] "1921-01-01 CET" "1929-01-01 CET" "1926-01-01 CET" "1921-01-01 CET" - [37] "1908-01-01 CET" "1928-01-01 CET" "1919-01-01 CET" "1921-01-01 CET" - [41] "1925-01-01 CET" "1934-01-01 CET" "1927-01-01 CET" "1928-01-01 CET" - [45] "1934-01-01 CET" "1922-01-01 CET" "1923-01-01 CET" "1915-01-01 CET" - [49] "1934-01-01 CET" "1925-01-01 CET" "1922-01-01 CET" "1930-01-01 CET" - [53] "1924-01-01 CET" "1923-01-01 CET" "1919-01-01 CET" "1932-01-01 CET" - [57] "1930-01-01 CET" "1923-01-01 CET" "1930-01-01 CET" "1922-01-01 CET" - [61] "1919-01-01 CET" "1932-01-01 CET" "1939-01-01 CET" "1923-01-01 CET" - [65] "1920-01-01 CET" "1919-01-01 CET" "1952-01-01 CET" "1927-01-01 CET" - [69] "1924-01-01 CET" "1919-01-01 CET" "1925-01-01 CET" "1945-01-01 CET" - [73] "1916-01-01 CET" "1943-01-01 CET" "1920-01-01 CET" "1920-01-01 CET" - [77] "1931-01-01 CET" "1924-01-01 CET" "1919-01-01 CET" "1926-01-01 CET" - [81] "1920-01-01 CET" "1952-01-01 CET" "1919-01-01 CET" "1930-01-01 CET" - [85] "1925-01-01 CET" "1924-01-01 CET" "1926-01-01 CET" "1918-01-01 CET" - [89] "1922-01-01 CET" "1921-01-01 CET" "1925-01-01 CET" "1928-01-01 CET" - [93] "1925-01-01 CET" "1929-01-01 CET" "1933-01-01 CET" "1947-01-01 CET" - [97] "1950-01-01 CET" "1945-01-01 CET" "1924-01-01 CET" "1939-01-01 CET" -[101] "1924-01-01 CET" "1933-01-01 CET" "1928-01-01 CET" + [1] "1937-01-01 GMT" "1916-01-01 GMT" "1913-01-01 GMT" "1927-01-01 GMT" + [5] "1947-01-01 GMT" "1913-01-01 GMT" "1917-01-01 GMT" "1923-01-01 GMT" + [9] "1921-01-01 GMT" "1926-01-01 GMT" "1920-01-01 GMT" "1915-01-01 GMT" + [13] "1914-01-01 GMT" "1914-01-01 GMT" "1914-01-01 GMT" "1919-01-01 GMT" + [17] "1948-01-01 GMT" "1911-01-01 GMT" "1909-01-01 GMT" "1913-01-01 GMT" + [21] "1925-01-01 GMT" "1926-01-01 GMT" "1910-01-01 GMT" "1917-01-01 GMT" + [25] "1936-01-01 GMT" "1938-01-01 GMT" "1960-01-01 GMT" "1915-01-01 GMT" + [29] "1919-01-01 GMT" "1924-01-01 GMT" "1914-01-01 GMT" "1905-01-01 GMT" + [33] "1921-01-01 GMT" "1929-01-01 GMT" "1926-01-01 GMT" "1921-01-01 GMT" + [37] "1908-01-01 GMT" "1928-01-01 GMT" "1919-01-01 GMT" "1921-01-01 GMT" + [41] "1925-01-01 GMT" "1934-01-01 GMT" "1927-01-01 GMT" "1928-01-01 GMT" + [45] "1934-01-01 GMT" "1922-01-01 GMT" "1923-01-01 GMT" "1915-01-01 GMT" + [49] "1934-01-01 GMT" "1925-01-01 GMT" "1922-01-01 GMT" "1930-01-01 GMT" + [53] "1924-01-01 GMT" "1923-01-01 GMT" "1919-01-01 GMT" "1932-01-01 GMT" + [57] "1930-01-01 GMT" "1923-01-01 GMT" "1930-01-01 GMT" "1922-01-01 GMT" + [61] "1919-01-01 GMT" "1932-01-01 GMT" "1939-01-01 GMT" "1923-01-01 GMT" + [65] "1920-01-01 GMT" "1919-01-01 GMT" "1952-01-01 GMT" "1927-01-01 GMT" + [69] "1924-01-01 GMT" "1919-01-01 GMT" "1925-01-01 GMT" "1945-01-01 GMT" + [73] "1916-01-01 GMT" "1943-01-01 GMT" "1920-01-01 GMT" "1920-01-01 GMT" + [77] "1931-01-01 GMT" "1924-01-01 GMT" "1919-01-01 GMT" "1926-01-01 GMT" + [81] "1920-01-01 GMT" "1952-01-01 GMT" "1919-01-01 GMT" "1930-01-01 GMT" + [85] "1925-01-01 GMT" "1924-01-01 GMT" "1926-01-01 GMT" "1918-01-01 GMT" + [89] "1922-01-01 GMT" "1921-01-01 GMT" "1925-01-01 GMT" "1928-01-01 GMT" + [93] "1925-01-01 GMT" "1929-01-01 GMT" "1933-01-01 GMT" "1947-01-01 GMT" + [97] "1950-01-01 GMT" "1945-01-01 GMT" "1924-01-01 GMT" "1939-01-01 GMT" +[101] "1924-01-01 GMT" "1933-01-01 GMT" "1928-01-01 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.teststrptime2 #argv <- list(character(0), '%X', ''); .Internal(strptime(argv[[1]], argv[[2]], argv[[3]])) @@ -45653,7 +46853,7 @@ character(0) ##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.teststrptime6 #argv <- list(c('2007-11-06', NA), '%Y-%m-%d', ''); .Internal(strptime(argv[[1]], argv[[2]], argv[[3]])) -[1] "2007-11-06 CET" NA +[1] "2007-11-06 GMT" NA ##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.teststrptime7 #argv <- list(c('20010101', NA, NA, '20041026'), '%Y%m%d', 'GMT'); .Internal(strptime(argv[[1]], argv[[2]], argv[[3]])) @@ -45661,12 +46861,20 @@ character(0) ##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.teststrptime8 #argv <- list('2002-02-02 02:02', '%Y-%m-%d %H:%M', ''); .Internal(strptime(argv[[1]], argv[[2]], argv[[3]])) -[1] "2002-02-02 02:02:00 CET" +[1] "2002-02-02 02:02:00 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.teststrptime9 #argv <- list(c('1890/01/01', '1891/01/01', '1892/01/01', '1893/01/01', '1894/01/01', '1895/01/01'), '%Y/%m/%d', ''); .Internal(strptime(argv[[1]], argv[[2]], argv[[3]])) -[1] "1890-01-01 CET" "1891-01-01 CET" "1892-01-01 CET" "1893-01-01 CET" -[5] "1894-01-01 CET" "1895-01-01 CET" +[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_strsplit.testStrSplit +#{ .Internal(strsplit("7", 42, F, F, F)) } +Error: non-character argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_strsplit.testStrSplit +#{ .Internal(strsplit(7, "42", F, F, F)) } +Error: non-character argument ##com.oracle.truffle.r.test.builtins.TestBuiltin_strsplit.testStrSplit #{ strsplit( c("helloh", "hi"), c("h","")) } @@ -45906,6 +47114,16 @@ character(0) #argv <- list(character(0), 8L); .Internal(strtoi(argv[[1]], argv[[2]])) integer(0) +##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 + "a" "foooo" "bb" "ccccc" "dd" NA + +##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(2L, 5L)) + 1 2 3 4 5 6 + "a" "foooo" "bb" "ccccc" "dd" NA + ##com.oracle.truffle.r.test.builtins.TestBuiltin_strtrim.teststrtrim1 #argv <- list(c('\'time\'', '\'status\''), 128); .Internal(strtrim(argv[[1]], argv[[2]])) [1] "'time'" "'status'" @@ -45989,6 +47207,26 @@ character(0) [1177] 14 15 16 17 13 14 15 16 17 Levels: 13 14 15 16 17 +##com.oracle.truffle.r.test.builtins.TestBuiltin_sub.testSub +#{ .Internal(sub("7", "42", 7, F, F, F, F)) } +Error: invalid 'text' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sub.testSub +#{ .Internal(sub("7", 42, "7", F, F, F, F)) } +Error: invalid 'replacement' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sub.testSub +#{ .Internal(sub("7", character(), "7", F, F, F, F)) } +Error: invalid 'replacement' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sub.testSub +#{ .Internal(sub(7, "42", "7", F, F, F, F)) } +Error: invalid 'pattern' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sub.testSub +#{ .Internal(sub(character(), "42", "7", F, F, F, F)) } +Error: invalid 'pattern' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_sub.testSub #{ sub("a","aa", "prague alley") } [1] "praague alley" @@ -46252,7 +47490,7 @@ Levels: McNeil R Core Ripley Tierney Tukey Venables ##com.oracle.truffle.r.test.builtins.TestBuiltin_subset.testsubset14 #argv <- list(structure(list(size = 1056, isdir = FALSE, mode = structure(420L, class = 'octmode'), mtime = structure(1393948130.23894, class = c('POSIXct', 'POSIXt')), ctime = structure(1393948130.23894, class = c('POSIXct', 'POSIXt')), atime = structure(1395074550.46596, class = c('POSIXct', 'POSIXt')), uid = 1001L, gid = 1001L, uname = 'roman', grname = 'roman'), .Names = c('size', 'isdir', 'mode', 'mtime', 'ctime', 'atime', 'uid', 'gid', 'uname', 'grname'), class = 'data.frame', row.names = '/home/roman/r-instrumented/library/grid/R/grid'), 'mtime');.subset(argv[[1]],argv[[2]]); $mtime -[1] "2014-03-04 16:48:50 CET" +[1] "2014-03-04 15:48:50 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_subset.testsubset15 @@ -46364,7 +47602,7 @@ NULL ##com.oracle.truffle.r.test.builtins.TestBuiltin_subset.testsubset24 #argv <- list(structure(list(size = 131, isdir = FALSE, mode = structure(436L, class = 'octmode'), mtime = structure(1386583148.91412, class = c('POSIXct', 'POSIXt')), ctime = structure(1386583148.91712, class = c('POSIXct', 'POSIXt')), atime = structure(1386583149.16512, class = c('POSIXct', 'POSIXt')), uid = 501L, gid = 501L, uname = 'lzhao', grname = 'lzhao'), .Names = c('size', 'isdir', 'mode', 'mtime', 'ctime', 'atime', 'uid', 'gid', 'uname', 'grname'), class = 'data.frame', row.names = 'startup.Rs'), 'mtime');.subset(argv[[1]],argv[[2]]); $mtime -[1] "2013-12-09 10:59:08 CET" +[1] "2013-12-09 09:59:08 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_subset.testsubset26 @@ -46572,7 +47810,7 @@ $`3` ##com.oracle.truffle.r.test.builtins.TestBuiltin_subset2.testsubset214 #argv <- list(structure(list(mtime = structure(1395082258.61787, class = c('POSIXct', 'POSIXt'))), .Names = 'mtime'), 1L);.subset2(argv[[1]],argv[[2]]); -[1] "2014-03-17 19:50:58 CET" +[1] "2014-03-17 18:50:58 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_subset2.testsubset215 #argv <- list(structure(list(A = 0:10, `NA` = 20:30), .Names = c('A', NA), class = 'data.frame', row.names = c(NA, -11L)), 2L);.subset2(argv[[1]],argv[[2]]); @@ -46655,7 +47893,7 @@ factor(0) ##com.oracle.truffle.r.test.builtins.TestBuiltin_subset2.testsubset229 #argv <- list(structure(list(mtime = structure(1342423171, class = c('POSIXct', 'POSIXt'))), .Names = 'mtime'), 1L);.subset2(argv[[1]],argv[[2]]); -[1] "2012-07-16 09:19:31 CEST" +[1] "2012-07-16 07:19:31 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_subset2.testsubset23 #argv <- list(structure(list(x = c(0, 0, 1, 1), y = c(2, 2, 9, 9), z = c(0, 0, -3, -3), u = c(34, 35, 19, 37)), .Names = c('x', 'y', 'z', 'u'), row.names = c(2L, 90L, 25L, 50L), class = 'data.frame'), 4L);.subset2(argv[[1]],argv[[2]]); @@ -46712,6 +47950,201 @@ NULL [2,] "b" "e" "h" [3,] "c" "f" "i" +##com.oracle.truffle.r.test.builtins.TestBuiltin_subset_dataframe.testsubset_dataframe1 +#argv <- structure(list(x = structure(list(ID = c(13, 41, 121, 202, 247, 292, 415, 492), Location = c(0.15998329123474, 0.533277637449134, 1.5998329123474, 2.6797201281819, 3.27965747031217, 3.87959481244245, 5.51942354759854, 6.54598299968812), Peak_Value = c(0.997547264684804, 0.949162789397664, 0.990440013891923, 0.973478735915337, 0.93861267739627, 0.957347289323235, 0.924803043529451, 0.968307855031101)), .Names = c('ID', 'Location', 'Peak_Value'), row.names = c(NA, -8L), class = 'data.frame'), i = 2), .Names = c('x', 'i'));do.call('[.data.frame', argv) + Location +1 0.1599833 +2 0.5332776 +3 1.5998329 +4 2.6797201 +5 3.2796575 +6 3.8795948 +7 5.5194235 +8 6.5459830 +Warning message: +In `[.data.frame`(x = list(ID = c(13, 41, 121, 202, 247, 292, 415, : + named arguments other than 'drop' are discouraged + +##com.oracle.truffle.r.test.builtins.TestBuiltin_subset_dataframe.testsubset_dataframe2 +#argv <- structure(list(x = structure(list(Satellites = c(8L, 0L, 9L, 0L, 4L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 11L, 0L, 14L, 8L, 1L, 1L, 0L, 5L, 4L, 3L, 1L, 2L, 3L, 0L, 3L, 5L, 0L, 0L, 4L, 0L, 0L, 8L, 5L, 0L, 0L, 6L, 0L, 6L, 3L, 5L, 6L, 5L, 9L, 4L, 6L, 4L, 3L, 3L, 5L, 5L, 6L, 4L, 5L, 15L, 3L, 3L, 0L, 0L, 0L, 5L, 3L, 5L, 1L, 8L, 10L, 0L, 0L, 3L, 7L, 1L, 0L, 6L, 0L, 0L, 3L, 4L, 0L, 5L, 0L, 0L, 0L, 4L, 0L, 3L, 0L, 0L, 0L, 0L, 5L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 4L, 1L, 1L, 1L, 1L, 2L, 4L, 3L, 6L, 0L, 2L, 2L, 0L, 12L, 0L, 5L, 6L, 6L, 2L, 0L, 2L, 3L, 0L, 3L, 4L, 2L, 6L, 6L, 0L, 4L, 10L, 7L, 0L, 5L, 5L, 6L, 6L, 7L, 3L, 3L, 0L, 0L, 8L, 4L, 4L, 10L, 9L, 4L, 0L, 0L, 0L, 0L, 4L, 0L, 2L, 0L, 4L, 4L, 3L, 8L, 0L, 7L, 0L, 0L, 2L, 3L, 4L, 0L, 0L, 0L), Width = c(28.3, 22.5, 26, 24.8, 26, 23.8, 26.5, 24.7, 23.7, 25.6, 24.3, 25.8, 28.2, 21, 26, 27.1, 25.2, 29, 24.7, 27.4, 23.2, 25, 22.5, 26.7, 25.8, 26.2, 28.7, 26.8, 27.5, 24.9, 29.3, 25.8, 25.7, 25.7, 26.7, 23.7, 26.8, 27.5, 23.4, 27.9, 27.5, 26.1, 27.7, 30, 28.5, 28.9, 28.2, 25, 28.5, 30.3, 24.7, 27.7, 27.4, 22.9, 25.7, 28.3, 27.2, 26.2, 27.8, 25.5, 27.1, 24.5, 27, 26, 28, 30, 29, 26.2, 26.5, 26.2, 25.6, 23, 23, 25.4, 24.2, 22.9, 26, 25.4, 25.7, 25.1, 24.5, 27.5, 23.1, 25.9, 25.8, 27, 28.5, 25.5, 23.5, 24, 29.7, 26.8, 26.7, 28.7, 23.1, 29, 25.5, 26.5, 24.5, 28.5, 28.2, 24.5, 27.5, 24.7, 25.2, 27.3, 26.3, 29, 25.3, 26.5, 27.8, 27, 25.7, 25, 31.9, 23.7, 29.3, 22, 25, 27, 23.8, 30.2, 26.2, 24.2, 27.4, 25.4, 28.4, 22.5, 26.2, 24.9, 24.5, 25.1, 28, 25.8, 27.9, 24.9, 28.4, 27.2, 25, 27.5, 33.5, 30.5, 29, 24.3, 25.8, 25, 31.7, 29.5, 24, 30, 27.6, 26.2, 23.1, 22.9, 24.5, 24.7, 28.3, 23.9, 23.8, 29.8, 26.5, 26, 28.2, 25.7, 26.5, 25.8, 24.1, 26.2, 26.1, 29, 28, 27, 24.5), Dark = structure(c(1L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 1L), .Label = c('no', 'yes'), class = 'factor'), GoodSpine = structure(c(1L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L), .Label = c('no', 'yes'), class = 'factor'), Rep1 = c(2, 4, 5, 6, 6, 8, 9, 9, 10, 10, 11, 11, 13, 15, 15, 15, 15, 15, 17, 18, 19, 19, 19, 20, 20, 21, 21, 22, 23, 25, 25, 26, 27, 27, 28, 29, 29, 31, 33, 33, 36, 39, 40, 40, 41, 42, 43, 44, 45, 45, 49, 50, 51, 53, 55, 55, 56, 56, 56, 58, 59, 59, 60, 60, 62, 63, 64, 64, 64, 65, 66, 66, 67, 68, 70, 70, 71, 74, 75, 76, 76, 77, 79, 79, 79, 80, 80, 81, 82, 83, 83, 84, 87, 88, 88, 91, 92, 95, 97, 97, 97, 98, 98, 99, 100, 100, 101, 101, 103, 103, 103, 106, 107, 107, 111, 112, 112, 113, 113, 116, 116, 117, 117, 120, 122, 122, 122, 124, 125, 126, 127, 128, 128, 129, 130, 131, 133, 134, 134, 135, 141, 144, 146, 147, 147, 153, 153, 154, 154, 155, 155, 155, 156, 157, 157, 161, 163, 163, 164, 164, 164, 165, 167, 168, 168, 169, 170, 170, 170, 171, 171, 173, 173), Rep2 = c(2, 5, 6, 6, 8, 8, 9, 11, 12, 13, 13, 15, 15, 15, 16, 17, 17, 18, 19, 20, 23, 24, 24, 24, 25, 25, 26, 26, 27, 28, 29, 30, 30, 32, 33, 34, 38, 39, 39, 41, 42, 47, 48, 49, 49, 51, 54, 55, 55, 56, 57, 59, 59, 62, 63, 65, 67, 68, 69, 69, 70, 73, 75, 76, 76, 77, 78, 79, 81, 82, 83, 84, 85, 85, 85, 86, 87, 88, 89, 91, 92, 92, 92, 92, 96, 98, 98, 99, 100, 101, 101, 102, 103, 104, 104, 104, 105, 107, 107, 107, 108, 109, 109, 110, 111, 111, 111, 112, 112, 112, 113, 113, 115, 116, 117, 120, 122, 123, 123, 124, 124, 125, 125, 126, 128, 130, 131, 131, 131, 131, 132, 133, 133, 134, 134, 136, 137, 138, 139, 139, 141, 143, 144, 144, 145, 145, 150, 150, 150, 152, 152, 153, 154, 155, 155, 156, 157, 157, 158, 159, 160, 161, 163, 163, 166, 167, 169, 170, 172, 173, 173, 173, 173)), .Names = c('Satellites', 'Width', 'Dark', 'GoodSpine', 'Rep1', 'Rep2'), row.names = c(NA, -173L), class = 'data.frame'), i = c(2, 4, 5, 6, 6, 8, 9, 9, 10, 10, 11, 11, 13, 15, 15, 15, 15, 15, 17, 18, 19, 19, 19, 20, 20, 21, 21, 22, 23, 25, 25, 26, 27, 27, 28, 29, 29, 31, 33, 33, 36, 39, 40, 40, 41, 42, 43, 44, 45, 45, 49, 50, 51, 53, 55, 55, 56, 56, 56, 58, 59, 59, 60, 60, 62, 63, 64, 64, 64, 65, 66, 66, 67, 68, 70, 70, 71, 74, 75, 76, 76, 77, 79, 79, 79, 80, 80, 81, 82, 83, 83, 84, 87, 88, 88, 91, 92, 95, 97, 97, 97, 98, 98, 99, 100, 100, 101, 101, 103, 103, 103, 106, 107, 107, 111, 112, 112, 113, 113, 116, 116, 117, 117, 120, 122, 122, 122, 124, 125, 126, 127, 128, 128, 129, 130, 131, 133, 134, 134, 135, 141, 144, 146, 147, 147, 153, 153, 154, 154, 155, 155, 155, 156, 157, 157, 161, 163, 163, 164, 164, 164, 165, 167, 168, 168, 169, 170, 170, 170, 171, 171, 173, 173), j = c(-5L, -6L)), .Names = c('x', 'i', 'j'));do.call('[.data.frame', argv) + Satellites Width Dark GoodSpine +2 0 22.5 yes no +4 0 24.8 yes no +5 4 26.0 yes no +6 0 23.8 no no +6.1 0 23.8 no no +8 0 24.7 yes yes +9 0 23.7 no yes +9.1 0 23.7 no yes +10 0 25.6 yes no +10.1 0 25.6 yes no +11 0 24.3 yes no +11.1 0 24.3 yes no +13 11 28.2 no no +15 14 26.0 no yes +15.1 14 26.0 no yes +15.2 14 26.0 no yes +15.3 14 26.0 no yes +15.4 14 26.0 no yes +17 1 25.2 no no +18 1 29.0 no no +19 0 24.7 yes no +19.1 0 24.7 yes no +19.2 0 24.7 yes no +20 5 27.4 no no +20.1 5 27.4 no no +21 4 23.2 no yes +21.1 4 23.2 no yes +22 3 25.0 no yes +23 1 22.5 no yes +25 3 25.8 yes no +25.1 3 25.8 yes no +26 0 26.2 yes no +27 3 28.7 no no +27.1 3 28.7 no no +28 5 26.8 no yes +29 0 27.5 yes no +29.1 0 27.5 yes no +31 4 29.3 no yes +33 0 25.7 no yes +33.1 0 25.7 no yes +36 0 23.7 yes no +39 0 23.4 yes no +40 6 27.9 no no +40.1 6 27.9 no no +41 3 27.5 yes no +42 5 26.1 no yes +43 6 27.7 no yes +44 5 30.0 no yes +45 9 28.5 yes yes +45.1 9 28.5 yes yes +49 3 28.5 no no +50 3 30.3 no yes +51 5 24.7 yes no +53 6 27.4 no yes +55 5 25.7 no yes +55.1 5 25.7 no yes +56 15 28.3 no no +56.1 15 28.3 no no +56.2 15 28.3 no no +58 3 26.2 yes no +59 0 27.8 no yes +59.1 0 27.8 no yes +60 0 25.5 yes no +60.1 0 25.5 yes no +62 5 24.5 yes no +63 3 27.0 yes yes +64 5 26.0 no no +64.1 5 26.0 no no +64.2 5 26.0 no no +65 1 28.0 no no +66 8 30.0 no no +66.1 8 30.0 no no +67 10 29.0 no no +68 0 26.2 no no +70 3 26.2 no no +70.1 3 26.2 no no +71 7 25.6 yes no +74 6 25.4 no no +75 0 24.2 yes no +76 0 22.9 no yes +76.1 0 22.9 no yes +77 3 26.0 yes yes +79 0 25.7 yes no +79.1 0 25.7 yes no +79.2 0 25.7 yes no +80 5 25.1 no no +80.1 5 25.1 no no +81 0 24.5 yes yes +82 0 27.5 yes no +83 0 23.1 yes no +83.1 0 23.1 yes no +84 4 25.9 yes yes +87 0 28.5 no no +88 0 25.5 yes yes +88.1 0 25.5 yes yes +91 5 29.7 no yes +92 0 26.8 no yes +95 0 23.1 yes no +97 0 25.5 yes no +97.1 0 25.5 yes no +97.2 0 25.5 yes no +98 1 26.5 yes no +98.1 1 26.5 yes no +99 1 24.5 yes no +100 1 28.5 yes no +100.1 1 28.5 yes no +101 1 28.2 no no +101.1 1 28.2 no no +103 1 27.5 no no +103.1 1 27.5 no no +103.2 1 27.5 no no +106 1 27.3 yes no +107 1 26.3 no no +107.1 1 26.3 no no +111 3 27.8 no no +112 6 27.0 no no +112.1 6 27.0 no no +113 0 25.7 yes no +113.1 0 25.7 yes no +116 0 23.7 yes no +116.1 0 23.7 yes no +117 12 29.3 yes no +117.1 12 29.3 yes no +120 6 27.0 yes no +122 2 30.2 no yes +122.1 2 30.2 no yes +122.2 2 30.2 no yes +124 2 24.2 no no +125 3 27.4 no no +126 0 25.4 no yes +127 3 28.4 yes no +128 4 22.5 yes no +128.1 4 22.5 yes no +129 2 26.2 no no +130 6 24.9 no yes +131 6 24.5 no yes +133 4 28.0 no yes +134 10 25.8 yes no +134.1 10 25.8 yes no +135 7 27.9 no no +141 7 33.5 no yes +144 0 24.3 no yes +146 8 25.0 yes no +147 4 31.7 no yes +147.1 4 31.7 no yes +153 0 23.1 no yes +153.1 0 23.1 no yes +154 0 22.9 no yes +154.1 0 22.9 no yes +155 0 24.5 yes no +155.1 0 24.5 yes no +155.2 0 24.5 yes no +156 4 24.7 no no +157 0 28.3 no no +157.1 0 28.3 no no +161 4 26.5 no no +163 8 28.2 no no +163.1 8 28.2 no no +164 0 25.7 yes no +164.1 0 25.7 yes no +164.2 0 25.7 yes no +165 7 26.5 no no +167 0 24.1 yes no +168 2 26.2 yes no +168.1 2 26.2 yes no +169 3 26.1 yes no +170 4 29.0 yes no +170.1 4 29.0 yes no +170.2 4 29.0 yes no +171 0 28.0 no yes +171.1 0 28.0 no yes +173 0 24.5 no yes +173.1 0 24.5 no yes +Warning message: +In `[.data.frame`(x = list(Satellites = c(8L, 0L, 9L, 0L, 4L, 0L, : + named arguments other than 'drop' are discouraged + ##com.oracle.truffle.r.test.builtins.TestBuiltin_substitute.testSubstitute #f<-function(...) { print(typeof(get('...'))); environment() }; e <- f(c(1,2), b=15, c=44); substitute(foo2({...}), e) [1] "..." @@ -47601,10 +49034,6 @@ In matrix(7:1, nrow = 5) : [4,] 11 15 19 -##com.oracle.truffle.r.test.builtins.TestBuiltin_sweep.testSweep -#{rowMeans(matrix(c(NaN,4+5i,2+0i,5+10i),nrow=2,ncol=2), na.rm = FALSE)} -[1] NA 4.5+7.5i - ##com.oracle.truffle.r.test.builtins.TestBuiltin_sweep.testsweep1 #argv <- structure(list(x = structure(integer(0), .Dim = c(5L, 0L)), MARGIN = 2, STATS = integer(0)), .Names = c('x', 'MARGIN', 'STATS'));do.call('sweep', argv) @@ -47952,6 +49381,39 @@ integer(0) #{ u <- function() sys.parents() ; f <- function(x) x ; g <- function(y) f(y) ; h <- function(z=u()) g(z) ; h() } [1] 0 1 2 1 +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTranspose +#t(1) + [,1] +[1,] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTranspose +#t(TRUE) + [,1] +[1,] TRUE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTranspose +#t(as.raw(c(1,2,3,4))) + [,1] [,2] [,3] [,4] +[1,] 01 02 03 04 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTranspose +#t(new.env()) +Error in t.default(new.env()) : argument is not a matrix + +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTranspose +#v <- as.complex(1:50); dim(v) <- c(5,10); dimnames(v) <- list(as.character(40:44), as.character(10:19)); t(v) + 40 41 42 43 44 +10 1+0i 2+0i 3+0i 4+0i 5+0i +11 6+0i 7+0i 8+0i 9+0i 10+0i +12 11+0i 12+0i 13+0i 14+0i 15+0i +13 16+0i 17+0i 18+0i 19+0i 20+0i +14 21+0i 22+0i 23+0i 24+0i 25+0i +15 26+0i 27+0i 28+0i 29+0i 30+0i +16 31+0i 32+0i 33+0i 34+0i 35+0i +17 36+0i 37+0i 38+0i 39+0i 40+0i +18 41+0i 42+0i 43+0i 44+0i 45+0i +19 46+0i 47+0i 48+0i 49+0i 50+0i + ##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTranspose #{ m <- double() ; dim(m) <- c(0,4) ; t(m) } @@ -48022,6 +49484,26 @@ c 2 [,1] [,2] [,3] [1,] -2.137774 1.170455 5.851801 +##com.oracle.truffle.r.test.builtins.TestBuiltin_tabulate.testTabulate +#{ .Internal(tabulate(c(2,3,5), 7)) } +Error: invalid input + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tabulate.testTabulate +#{ .Internal(tabulate(c(2L,3L,5L), -1)) } +Error: invalid 'nbin' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tabulate.testTabulate +#{ .Internal(tabulate(c(2L,3L,5L), NA)) } +Error: invalid 'nbin' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tabulate.testTabulate +#{ .Internal(tabulate(c(2L,3L,5L), c(7, 42))) } +[1] 0 1 1 0 1 0 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tabulate.testTabulate +#{ .Internal(tabulate(c(2L,3L,5L), integer())) } +Error: invalid 'nbin' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_tabulate.testTabulate #{tabulate(c(-2,0,2,3,3,5))} [1] 0 1 2 0 1 @@ -48754,6 +50236,42 @@ Volume 55.4 55.7 58.3 51.5 51 77.0 [4,] 0.47180794+0i -0.009784296+0i 0.08254997+0i 0.09431439+0i 0.87269229+0i [5,] -0.63291053+0i 0.283760917+0i 0.54536410+0i 0.39826963+0i 0.25072556+0i +##com.oracle.truffle.r.test.builtins.TestBuiltin_tempfile.testTempfile +#{ tempfile("file", 42) } +Error in tempfile("file", 42) : invalid 'tempdir' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tempfile.testTempfile +#{ tempfile("file", character()) } +Error in tempfile("file", character()) : no 'tempdir' + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tempfile.testTempfile +#{ tempfile("file", integer()) } +Error in tempfile("file", integer()) : invalid 'tempdir' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tempfile.testTempfile +#{ tempfile("file", tempdir(), 42) } +Error in tempfile("file", tempdir(), 42) : invalid file extension + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tempfile.testTempfile +#{ tempfile("file", tempdir(), character()) } +Error in tempfile("file", tempdir(), character()) : no 'fileext' + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tempfile.testTempfile +#{ tempfile("file", tempdir(), integer()) } +Error in tempfile("file", tempdir(), integer()) : invalid file extension + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tempfile.testTempfile +#{ tempfile(42) } +Error in tempfile(42) : invalid filename pattern + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tempfile.testTempfile +#{ tempfile(character()) } +Error in tempfile(character()) : no 'pattern' + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tempfile.testTempfile +#{ tempfile(integer()) } +Error in tempfile(integer()) : invalid filename pattern + ##com.oracle.truffle.r.test.builtins.TestBuiltin_times_difftime.testtimes_difftime1 #argv <- structure(list(e1 = 2, e2 = structure(c(3.33333333333333, 683.25), units = 'mins', class = 'difftime')), .Names = c('e1', 'e2'));do.call('*.difftime', argv) Time differences in mins @@ -49078,25 +50596,25 @@ Error in tracemem(NULL) : cannot trace NULL ##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.list #v <- list(1,10,100); tracemem(v); x <- v; x[[1]]<-42; -[1] "<0x112db18>" -tracemem[0x112db18 -> 0x1699c30]: +[1] "<0x7fc00f8ddc08>" +tracemem[0x7fc00f8ddc08 -> 0x7fc00f8e3118]: ##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.retracemem #v <- c(1,10,100); tracemem(v); x <- v[-1]; retracemem(x, retracemem(v)); u <- x; u[[1]] <- 42; -[1] "<0x17f8b18>" -tracemem[<0x17f8b18> -> 0x251dd78]: -tracemem[0x251dd78 -> 0x251ddb0]: +[1] "<0x7f81ef033608>" +tracemem[<0x7f81ef033608> -> 0x7f81ef01c838]: +tracemem[0x7f81ef01c838 -> 0x7f81ef01c870]: ##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.vectors #v <- c(1,10,100); tracemem(v); x <- v; y <- v; x[[1]]<-42; untracemem(v); y[[2]] <- 84 -[1] "<0x1b8eb18>" -tracemem[0x1b8eb18 -> 0x20fabe8]: +[1] "<0x7fb7ac283c08>" +tracemem[0x7fb7ac283c08 -> 0x7fb7ac289040]: ##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.vectors #v <- c(1,10,100); tracemem(v); x <- v; y <- v; x[[1]]<-42; y[[2]] <- 84 -[1] "<0x24b2b18>" -tracemem[0x24b2b18 -> 0x2a1ebe8]: -tracemem[0x24b2b18 -> 0x2a1ea80]: +[1] "<0x7fc4d531e608>" +tracemem[0x7fc4d531e608 -> 0x7fc4d5323a40]: +tracemem[0x7fc4d531e608 -> 0x7fc4d5323968]: ##com.oracle.truffle.r.test.builtins.TestBuiltin_trigamma.testtrigamma1 #argv <- list(structure(c(9.16602362697115, 1.16602362697115, 3.16602362697115, 6.16602362697115, 6.16602362697115, 2.16602362697115, 8.16602362697115, 1.16602362697115, 7.16602362697115, 19.1660236269712, 2.16602362697115), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11')));trigamma(argv[[1]]); @@ -49686,8 +51204,8 @@ $b Levels: A B C $a -[1] "2013-12-07 14:46:21 CET" "2013-12-07 09:13:01 CET" -[3] "2013-12-07 11:59:41 CET" +[1] "2013-12-07 13:46:21 GMT" "2013-12-07 08:13:01 GMT" +[3] "2013-12-07 10:59:41 GMT" attr(,"row.names") [1] 3 1 2 @@ -50110,6 +51628,19 @@ attr(,"row.names") "3rd Qu.: 7.75 " "3rd Qu.: 7.75 3rd Qu.:17.75 " "Max. :10.00 " "Max. :10.00 Max. :20.00 " +##com.oracle.truffle.r.test.builtins.TestBuiltin_unique.testUnique +#{ unique(c(1,2,1), incomparables=function() 42) } +Error in unique.default(c(1, 2, 1), incomparables = function() 42) : + cannot coerce type 'closure' to vector of type 'double' + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unique.testUnique +#{ x<-function() 42; unique(x) } +Error in unique.default(x) : unique() applies only to vectors + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unique.testUnique +#{ x<-quote(f(7, 42)); unique(x) } +Error in unique.default(x) : unique() applies only to vectors + ##com.oracle.truffle.r.test.builtins.TestBuiltin_unique.testUnique #{x<-factor(c("a", "b", "a")); unique(x) } [1] a b @@ -50678,9 +52209,9 @@ attr(,"Rd_tag") ##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist15 #argv <- list(list(structure(list(structure(c(1395082040.29392, 1395082040.29392, 1395082040.29392, 1395082040.29392, 1395082040.29392), class = c('AsIs', 'POSIXct', 'POSIXt'))), row.names = c(NA, -5L), class = 'data.frame')), FALSE, FALSE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]])) [[1]] -[1] "2014-03-17 19:47:20 CET" "2014-03-17 19:47:20 CET" -[3] "2014-03-17 19:47:20 CET" "2014-03-17 19:47:20 CET" -[5] "2014-03-17 19:47:20 CET" +[1] "2014-03-17 18:47:20 GMT" "2014-03-17 18:47:20 GMT" +[3] "2014-03-17 18:47:20 GMT" "2014-03-17 18:47:20 GMT" +[5] "2014-03-17 18:47:20 GMT" ##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist16 @@ -51422,6 +52953,30 @@ function (x) { x } #{ iv <- integer(1); iv[[1]] = 1L; vapply(c(1L, 2L, 3L, 4L), function(x) x+5L, iv) } [1] 6 7 8 9 +##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapply +#{ vapply(c("foo", "bar"), 42, c(TRUE) } +Error: unexpected '}' in "{ vapply(c("foo", "bar"), 42, c(TRUE) }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapply +#{ vapply(c("foo", "bar"), function(x) FALSE, c(TRUE), USE.NAMES="42") } +Error in vapply(c("foo", "bar"), function(x) FALSE, c(TRUE), USE.NAMES = "42") : + invalid 'USE.NAMES' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapply +#{ vapply(c("foo", "bar"), function(x) FALSE, c(TRUE), USE.NAMES=42) } + foo bar +FALSE FALSE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapply +#{ vapply(c("foo", "bar"), function(x) FALSE, c(TRUE), USE.NAMES=logical()) } +Error in vapply(c("foo", "bar"), function(x) FALSE, c(TRUE), USE.NAMES = logical()) : + invalid 'USE.NAMES' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapply +#{ vapply(c("foo", "bar"), function(x) FALSE, function() 42) } +Error in vapply(c("foo", "bar"), function(x) FALSE, function() 42) : + 'FUN.VALUE' must be a vector + ##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapply #{ vapply(c("hello", "goodbye", "up", "down"), function(x) x, c("a")) } hello goodbye up down @@ -51455,6 +53010,14 @@ function (x) { x } #{ vapply(c(TRUE, FALSE, TRUE), function(x) x, c(TRUE)) } [1] TRUE FALSE TRUE +##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorConstructor +#{ vector("numeric", c(7, 42)) } +Error in vector("numeric", c(7, 42)) : invalid 'length' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorConstructor +#{ vector("numeric", integer()) } +Error in vector("numeric", integer()) : invalid 'length' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorConstructor #{ vector("integer") } integer(0) @@ -51471,6 +53034,14 @@ numeric(0) #{ vector() } logical(0) +##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorConstructor +#{ vector(c("numeric", "numeric")) } +Error in vector(c("numeric", "numeric")) : invalid 'mode' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorConstructor +#{ vector(character()) } +Error in vector(character()) : invalid 'mode' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorConstructor #{ vector(length=3) } [1] FALSE FALSE FALSE @@ -53590,6 +55161,11 @@ Levels: Control Treat Warning message: In rm("ieps") : object 'ieps' not found +##com.oracle.truffle.r.test.builtins.TestMiscBuiltins.testSimpleRm +#{ rm("sum", envir=getNamespace("stats")) } +Error in rm("sum", envir = getNamespace("stats")) : + cannot remove bindings from a locked environment + ##com.oracle.truffle.r.test.builtins.TestMiscBuiltins.testSimpleRm #{ x <- 200 ; rm("x") ; x } Error: object 'x' not found @@ -55107,7 +56683,7 @@ Error: attempt to apply non-function function (x, where = -1, envir = if (missing(frame)) as.environment(where) else sys.frame(frame), frame, mode = "any", inherits = TRUE) .Internal(exists(x, envir, mode, inherits)) -<bytecode: 0x7fcdc2177910> +<bytecode: 0x7fefe285a310> <environment: namespace:base> ##com.oracle.truffle.r.test.functions.TestFunctions.testFunctionPrinting @@ -55383,7 +56959,7 @@ Error in foo(1, 2, 3) : unused arguments (2, 3) [1] TRUE ##com.oracle.truffle.r.test.functions.TestS3Dispatch.runRSourceTests -#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/S3/R/argMatching.R") } +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/functions/S3/R/argMatching.R") } dispatch g.c args: [[1]] @@ -55669,32 +57245,32 @@ Error in tryCatchList(expr, classes, parentenv, handlers) : fred [1] "Hello" ##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadBin -#{ readBin(file("com.oracle.truffle.r.test/library.base.conn/wb1", "rb"), 3) } +#{ readBin(file("tmptest/com.oracle.truffle.r.test.library.base.conn/wb1", "rb"), 3) } numeric(0) ##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadBin -#{ writeBin("abc", file("com.oracle.truffle.r.test/library.base.conn/wb1", open="wb")) } +#{ writeBin("abc", file("tmptest/com.oracle.truffle.r.test.library.base.conn/wb1", open="wb")) } ##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadChar -#{ readChar(file("com.oracle.truffle.r.test/library.base.conn/wc1"), 3) } +#{ readChar(file("tmptest/com.oracle.truffle.r.test.library.base.conn/wc1"), 3) } [1] "abc" ##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadChar -#{ writeChar("abc", file("com.oracle.truffle.r.test/library.base.conn/wc1")) } +#{ writeChar("abc", file("tmptest/com.oracle.truffle.r.test.library.base.conn/wc1")) } ##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadLines -#{ con <- file("com.oracle.truffle.r.test/library.base.conn/wl2"); readLines(con, 2) } +#{ con <- file("tmptest/com.oracle.truffle.r.test.library.base.conn/wl2"); readLines(con, 2) } [1] "line1" "line2" ##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadLines -#{ con <- file("com.oracle.truffle.r.test/library.base.conn/wl2"); writeLines(c("line1", "line2"), con) } +#{ con <- file("tmptest/com.oracle.truffle.r.test.library.base.conn/wl2"); writeLines(c("line1", "line2"), con) } ##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadLines -#{ readLines(file("com.oracle.truffle.r.test/library.base.conn/wl1"), 2) } +#{ readLines(file("tmptest/com.oracle.truffle.r.test.library.base.conn/wl1"), 2) } [1] "line1" "line2" ##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadLines -#{ writeLines(c("line1", "line2"), file("com.oracle.truffle.r.test/library.base.conn/wl1")) } +#{ writeLines(c("line1", "line2"), file("tmptest/com.oracle.truffle.r.test.library.base.conn/wl1")) } ##com.oracle.truffle.r.test.library.base.TestConnections.testPushBackTextConnection #{ con<-textConnection(c("a","b","c","d")); pushBack("G", con); clearPushBack(con); pushBackLength(con) } @@ -58521,6 +60097,10 @@ logical(0) #{ x<-c(1,2,3);x+TRUE } [1] 2 3 4 +##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsComplex +#x <- c(NaN, 3+2i); xre <- Re(x); xim <- (0+1i) * Im(x); xre + xim +[1] NA 3+2i + ##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsComplex #{ 1:4+c(1,2+2i) } [1] 2+0i 4+2i 4+0i 6+2i @@ -60594,6 +62174,24 @@ $vectors #{ attributes(NULL) } NULL +##com.oracle.truffle.r.test.library.base.TestSimpleAttributes.testDefinition +#{ f<-function() 42; attr(f, '.Environment')<-baseenv(); attr(f, '.Environment') } +<environment: base> + +##com.oracle.truffle.r.test.library.base.TestSimpleAttributes.testDefinition +#{ f<-function() 42; attr(f, '.Environment')<-baseenv(); environment(f) } +<environment: R_GlobalEnv> + +##com.oracle.truffle.r.test.library.base.TestSimpleAttributes.testDefinition +#{ f<-function() 42; attributes(f)<-list(.Environment=baseenv()); attributes(f) } +$.Environment +<environment: base> + + +##com.oracle.truffle.r.test.library.base.TestSimpleAttributes.testDefinition +#{ f<-function() 42; attributes(f)<-list(.Environment=baseenv()); environment(f) } +<environment: R_GlobalEnv> + ##com.oracle.truffle.r.test.library.base.TestSimpleAttributes.testDefinition #{ f<-function(y) attr(y, "foo")<-NULL; x<-function() 42; attr(x, "foo")<-"foo"; s<-"bar"; switch(s, f(x)); x } function() 42 @@ -60711,6 +62309,32 @@ $a [1] "1" +##com.oracle.truffle.r.test.library.base.TestSimpleAttributes.testDefinition +#{ x<-42; attr(x, '.Environment')<-globalenv(); attr(x, '.Environment') } +<environment: R_GlobalEnv> + +##com.oracle.truffle.r.test.library.base.TestSimpleAttributes.testDefinition +#{ x<-42; attr(x, '.Environment')<-globalenv(); attr(x, '.Environment')<-NULL; environment(x) } +NULL + +##com.oracle.truffle.r.test.library.base.TestSimpleAttributes.testDefinition +#{ x<-42; attr(x, '.Environment')<-globalenv(); environment(x) } +<environment: R_GlobalEnv> + +##com.oracle.truffle.r.test.library.base.TestSimpleAttributes.testDefinition +#{ x<-42; attributes(x)<-list(.Environment=globalenv()); attributes(x) } +$.Environment +<environment: R_GlobalEnv> + + +##com.oracle.truffle.r.test.library.base.TestSimpleAttributes.testDefinition +#{ x<-42; attributes(x)<-list(.Environment=globalenv()); attributes(x)<-NULL; environment(x) } +NULL + +##com.oracle.truffle.r.test.library.base.TestSimpleAttributes.testDefinition +#{ x<-42; attributes(x)<-list(.Environment=globalenv()); environment(x) } +<environment: R_GlobalEnv> + ##com.oracle.truffle.r.test.library.base.TestSimpleAttributes.testDefinition #{ x<-array(1:4, c(2,2), list(c(1,2), c(3,4))); attributes(x) } $dim @@ -62445,6 +64069,30 @@ NULL ##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIfWithoutElseIgnore #if(FALSE) 1 +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testAvoidingCopying +#a<-list(); a$x <- c(1,2,3); ident <- function(q)q; invisible(tracemem(a$x)); a$x[[1]] <- ident(a$x[[2]]); a$x +[1] 2 2 3 + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testAvoidingCopying +#a<-list(); a$x <- c(1,2,3); invisible(tracemem(a$x)); a$x[[1]] <- a$x[[2]] * 3; a$x +[1] 6 2 3 + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testAvoidingCopying +#a<-list(); a$x <- c(1,2,3); invisible(tracemem(a$x)); a$y <- 'dummy'; a$x[[1]] <- a$x[[2]] * 3; a$x +[1] 6 2 3 + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testAvoidingCopying +#l <- list(); l$x <- c(NA); length(l$x) <- 10; l$x[1] <- 42; invisible(tracemem(l$x)); l$x[2:9] <- 42; + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testAvoidingCopying +#l <- list(x=c(NA,NA)); l$x[1] <- 42; invisible(tracemem(l$x)); l$x[2] <- 42; + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testAvoidingCopying +#x <- list(c(1,2,3)); invisible(tracemem(x)); x[[1]] <- 42; + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testAvoidingCopying +#z <- c(1,4,8); invisible(tracemem(z)); a<-list(); a$x <- z; + ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess #{ a <- list(1,2,3) ; x <- integer() ; a[[x]] } Error in a[[x]] : attempt to select less than one element @@ -62644,6 +64292,266 @@ list() list() +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListDuplication +#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { l <- list(x=c(3,4,5)); id <- .fastr.identity(l$x); l$x <- 1:10; id == .fastr.identity(l$x) } +[1] FALSE + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListDuplication +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { l <- list(x=c(3,4,5)); id <- .fastr.identity(l$x); l$x[2] <- 10; id == .fastr.identity(l$x) } +[1] TRUE + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListDuplication +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { l <- list(x=c(3,4,5)); id <- .fastr.identity(l); l$x[2] <- 10; id == .fastr.identity(l) } +[1] TRUE + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#a <- list(); a$x <- c(1,2,3); b <- a; a$x[[1]] <- 4; b +$x +[1] 1 2 3 + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#a <- list(); a$y <- 'dummy'; a$x <- c(1,2,3); b <- a; a$x[[1]] <- 4; b +$y +[1] "dummy" + +$x +[1] 1 2 3 + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#a <- list(); a$y <- 'dummy'; b <- a; a$x <- c(1,2,3); a$x[[1]] <- 4; b +$y +[1] "dummy" + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#a <- list(x=1); b <- a; a$x[[1]] <- 42; list(a=a,b=b) +$a +$a$x +[1] 42 + + +$b +$b$x +[1] 1 + + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#a <- list(x=c(1,2,10)); b <- list(); b$x <- c(1,42); swap <- a; a <- b; b <- swap; a$x[[2]] <- 3; list(a=a, b=b) +$a +$a$x +[1] 1 3 + + +$b +$b$x +[1] 1 2 10 + + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#a <- list(x=c(1,2,3)); b <- a; a$x[[1]] <- 4; b +$x +[1] 1 2 3 + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#a <- list(x=list(y=c(1,2,4))); b <- a$x; b$y[[1]] <- 42; list(a=a,b=b) +$a +$a$x +$a$x$y +[1] 1 2 4 + + + +$b +$b$y +[1] 42 2 4 + + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#a <- list(x=list(y=c(1,2,4))); b <- a$x; c <- b; c$y[[1]] <- 42; list(a=a,b=b,c=c) +$a +$a$x +$a$x$y +[1] 1 2 4 + + + +$b +$b$y +[1] 1 2 4 + + +$c +$c$y +[1] 42 2 4 + + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#a <- list(x=list(y=c(1,2,4))); b <- a; b$x$y[[1]] <- 42; list(a=a,b=b) +$a +$a$x +$a$x$y +[1] 1 2 4 + + + +$b +$b$x +$b$x$y +[1] 42 2 4 + + + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#f <- function(l) l$x[[1]]<-42; a <- list(x=c(1,2,4)); b <- a; f(b); list(a=a, b=b) +$a +$a$x +[1] 1 2 4 + + +$b +$b$x +[1] 1 2 4 + + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#f <- function(l) l$x[[1]]<-42; a <- list(x=c(1,2,4)); f(a); a +$x +[1] 1 2 4 + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#f <- function(l) l; a <- list(x=c(1,2,4)); b <- f(a); b$x[[1]] <- 42; list(a=a, b=b) +$a +$a$x +[1] 1 2 4 + + +$b +$b$x +[1] 42 2 4 + + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#l <- list(k=list()); k <- list(l=list()); l$k <- k; k$l <- l; k$l$x <- 42; list(k=k, l=l) +$k +$k$l +$k$l$k +$k$l$k$l +list() + + +$k$l$x +[1] 42 + + + +$l +$l$k +$l$k$l +list() + + + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#l <- list(k=list()); k <- list(x=c(1,10)); l$k <- k; l$k$x[1] <- 42; list(l_k=l$k$x, k=k$x); +$l_k +[1] 42 10 + +$k +[1] 1 10 + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#l <- list(list(list())); l[[1]][[1]] <- l; l +[[1]] +[[1]][[1]] +[[1]][[1]][[1]] +[[1]][[1]][[1]][[1]] +list() + + + + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#l <- list(x=list()); v <- list(y=42,x=list()); v$x <- l; l$x <- v; l$y <- 44; k <- v; k$y <- 45; list(l=l,v=v,k=k); +$l +$l$x +$l$x$y +[1] 42 + +$l$x$x +$l$x$x$x +list() + + + +$l$y +[1] 44 + + +$v +$v$y +[1] 42 + +$v$x +$v$x$x +list() + + + +$k +$k$y +[1] 45 + +$k$x +$k$x$x +list() + + + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#r <- split(1,1); r[[1]] / 2; r; +[1] 0.5 +$`1` +[1] 1 + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#r <- split(1,1); x <- r; r[[1]] <- 42; x; +$`1` +[1] 1 + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#x <- c(1,2,3); l <- list(x); x[[1]] <- 42; l; +[[1]] +[1] 1 2 3 + + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting +#z <- c(1,4,8); a<-list(); a$x <- z; a$x[[1]] <- 42; list(a=a, z=z) +$a +$a$x +[1] 42 4 8 + + +$z +[1] 1 4 8 + + ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListUpdate #{ l <- list(c(1,2,3),c(4,5,6)) ; l[[1]] <- c(7,8,9) ; l[[1]] } [1] 7 8 9 @@ -62785,7 +64693,7 @@ Error in while (1 < NA) { : missing value where TRUE/FALSE needed ##com.oracle.truffle.r.test.library.base.TestSimpleLoop.testLoopsErrorsIgnore #{ l <- function(s) { for(i in s) { x <- i } ; x } ; l(1:3) ; s <- function(){} ; l(s) ; x } -Error in l(s) : object 'x' not found +Error in for (i in s) { : invalid for() loop sequence ##com.oracle.truffle.r.test.library.base.TestSimpleLoop.testLoopsErrorsIgnore #{ l <- quote(for(i in s) { x <- i }) ; s <- 1:3 ; eval(l) ; s <- function(){} ; eval(l) ; x } @@ -97409,7 +99317,8 @@ Error in z[[list()]] <- 42 : attempt to select less than one element ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testListIndex #{ z<-1:4; z[[list()]]<-NULL } -Error in z[[list()]] <- NULL : attempt to select less than one element +Error in z[[list()]] <- NULL : + more elements supplied than there are to replace ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testListIndex #{ z<-1:4; z[[list()]]<-integer() } @@ -97425,8 +99334,7 @@ Error in z[[list(1)]] <- 42 : invalid subscript type 'list' ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testListIndex #{ z<-1:4; z[[list(1)]]<-NULL } -Error in z[[list(1)]] <- NULL : - more elements supplied than there are to replace +Error in z[[list(1)]] <- NULL : invalid subscript type 'list' ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testListIndex #{ z<-1:4; z[[list(1)]]<-integer() } @@ -97663,7 +99571,8 @@ a ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testListUpdate #{ f <- function(b,i,v) { b[[i]] <- v ; b } ; f(list(1,2,b=list(a=1)),c("b","a"),10) ; f(c(a=1,b=2),"b",NULL) } -Error in b[[i]] <- v : more elements supplied than there are to replace +Error in b[[i]] <- v : + incompatible types (from NULL to double) in [[ assignment ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testListUpdate #{ f <- function(b,i,v) { b[[i]] <- v ; b } ; f(list(1,2,b=list(a=1)),c("b","a"),10) ; f(c(a=1,b=2),"b",as.raw(12)) } @@ -97790,7 +99699,8 @@ Error in b[[i]] <- v : more elements supplied than there are to replace ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testListUpdate #{ f <- function(b,i,v) { b[[i]] <- v ; b } ; f(list(1,2,list(3)), c(3,1), 4) ; f(c(1,2,3), 2L, NULL) } -Error in b[[i]] <- v : more elements supplied than there are to replace +Error in b[[i]] <- v : + incompatible types (from NULL to double) in [[ assignment ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testListUpdate #{ f <- function(b,i,v) { b[[i]] <- v ; b } ; f(list(1,2,list(3)), c(3,1), 4) ; f(c(1,2,3), f, 2) } @@ -99007,8 +100917,7 @@ NULL ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther #{ b<-3:5; dim(b) <- c(1,3) ; b[[0]] <- NULL ; b } -Error in b[[0]] <- NULL : - more elements supplied than there are to replace +Error in b[[0]] <- NULL : attempt to select less than one element ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther #{ b<-3:5; dim(b) <- c(1,3) ; b[[c(1)]] <- NULL ; b } @@ -99538,18 +101447,15 @@ Error in x[[NA]] <- NULL : attempt to select more than one element ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther #{ x <- c(1,2,3) ; x[[NA]] <- NULL ; x } -Error in x[[NA]] <- NULL : - more elements supplied than there are to replace +Error in x[[NA]] <- NULL : attempt to select more than one element ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther #{ x <- c(1,2,3); x[[-1]] <- NULL } -Error in x[[-1]] <- NULL : - more elements supplied than there are to replace +Error in x[[-1]] <- NULL : attempt to select more than one element ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther #{ x <- integer() ; x[[NA]] <- NULL ; x } -Error in x[[NA]] <- NULL : - more elements supplied than there are to replace +Error in x[[NA]] <- NULL : attempt to select less than one element ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther #{ x <- list() ; x[[NA]] <- NULL ; x } @@ -100095,7 +102001,8 @@ In x[1] <- c(1, 1) : ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther #{ x<-1:4; x[[0]]<-NULL; x } -Error in x[[0]] <- NULL : attempt to select less than one element +Error in x[[0]] <- NULL : + more elements supplied than there are to replace ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther #{ x<-1:4; x[[1]]<-NULL; x } @@ -100403,7 +102310,7 @@ Error in x[1] <- NULL : replacement has length zero ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther #{ x<-c(1,2,3,4); dim(x)<-c(2,2); x[[1,1]]<-NULL; x } Error in x[[1, 1]] <- NULL : - more elements supplied than there are to replace + incompatible types (from NULL to double) in [[ assignment ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther #{ x<-c(1,2,3,4); dim(x)<-c(2,2); x[[1]]<-NULL; x } @@ -100412,8 +102319,8 @@ Error in x[[1]] <- NULL : ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther #{ x<-c(1,2,3,4); dim(x)<-c(2,2); x[[as.raw(1), 1]]<-NULL } -Error in x[[as.raw(1), 1]] <- NULL : - more elements supplied than there are to replace +Error in `[[<-`(`*tmp*`, as.raw(1), 1, value = NULL) : + invalid subscript type 'raw' ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther #{ x<-c(5,10); names(x)<-c(101, 102); names(x)[1]<-42; x } @@ -102906,7 +104813,8 @@ Error in `[<-`(`*tmp*`, as.raw(1), 1, value = integer(0)) : ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testRawIndex #{ x<-c(1,2,3,4); x[[as.raw(1)]]<-NULL } -Error in x[[as.raw(1)]] <- NULL : invalid subscript type 'raw' +Error in x[[as.raw(1)]] <- NULL : + more elements supplied than there are to replace ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testRawIndex #{ x<-c(1,2,3,4); x[[as.raw(1)]]<-c(1) } @@ -104296,7 +106204,8 @@ Error in b[2] <- v : ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarUpdate #{ f <- function(b,v) { b[[2]] <- v ; b } ; f(c("a","b"),"d") ; f(c("a","b"),NULL) } -Error in b[[2]] <- v : more elements supplied than there are to replace +Error in b[[2]] <- v : + incompatible types (from NULL to character) in [[ assignment ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarUpdate #{ f <- function(b,v) { b[[2]] <- v ; b } ; f(list(TRUE,NA),FALSE) ; f(3,3) } @@ -104355,7 +106264,7 @@ Error in x[[as.integer(NA)]] <- 10 : ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarUpdate #{ x <- 4:10 ; x[["z"]] <- NULL ; x } Error in x[["z"]] <- NULL : - incompatible types (from NULL to integer) in [[ assignment + more elements supplied than there are to replace ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarUpdate #{ x <- as.list(1:2) ; x[["z"]] <- NULL ; x } @@ -104854,6 +106763,10 @@ $X #{ f <- function(a, i1, i2) {a[i1, i2]}; a <- rep(c('1'),14); dim(a) <- c(2,7); dimnames(a) <- list(c('a','b'), rep('c',7)); temp <- f(a, ,1); dimnames(a) <- list(NULL, rep('c',7)); f(a,,1) } [1] "1" "1" +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testUpdateOther +#{ x<-as.pairlist(list(7,42)); x[character(0)]<-list(); typeof(x) } +[1] "list" + ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testUpdateOther #{ x<-c(1,2); f<-function() { x<-c(100, 200); x[1]<-4; print(x) } ; f(); x } [1] 4 200 @@ -104864,6 +106777,14 @@ $X [1] 100 200 [1] 4 2 +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testUpdateOther +#{ x<-expression(y, z, 7 + 42); x[character(0)]<-list(); typeof(x) } +[1] "expression" + +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testUpdateOther +#{ x<-quote(foo(42)); x[character(0)]<-list(); typeof(x) } +[1] "language" + ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorIndex # { f <- function(b,i) { b[i] } ; f(c(a=1,b=2,c=3), c(TRUE,NA)) } a <NA> c @@ -107035,26 +108956,186 @@ a b c d a b c d e 1 2 3 4 5 -##com.oracle.truffle.r.test.library.fastr.TestInteropEval.testInteropEval +##com.oracle.truffle.r.test.library.fastr.TestChannels.dummyTest +#42 +[1] 42 + +##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels1.R") } +[1] 7 42 + +##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels10.R") } +[1] 7 42 + +##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels11.R") } +[1] 7 42 + +##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels12.R") } +[[1]] +[1] 7 + +[[2]] +[1] 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/channels13.R") } +[[1]] +[1] 7 42 + +[[2]] +[1] FALSE 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/channels14.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/channels15.R") } +[[1]] +[1] "baz" "bar" + +[[2]] +[1] "foo" "bar" + + +##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels16.R") } +[1] 7 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/channels17.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/channels2.R") } +[[1]] +[1] 7 + +[[2]] +[1] 42 + + +##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels3.R") } +[1] 49 + +##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels4.R") } +[[1]] +[1] 7 + +[[2]] +[1] 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/channels5.R") } +[[1]] +[1] 7 + +[[2]] +[1] 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/channels6.R") } +[[1]] +[1] 7 + +[[2]] +[1] 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/channels7.R") } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels8.R") } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests +#{ 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.TestInterop.testInteropEval #if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { .fastr.interop.eval('application/x-r', '1') } [1] 1 -##com.oracle.truffle.r.test.library.fastr.TestInteropEval.testInteropEval +##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval #if (length(grep("FastR", R.Version()$version.string)) != 1) { 16 } else { .fastr.interop.eval('application/x-r', '14 + 2') } [1] 16 -##com.oracle.truffle.r.test.library.fastr.TestInteropEval.testInteropEval +##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval #if (length(grep("FastR", R.Version()$version.string)) != 1) { 1L } else { .fastr.interop.eval('application/x-r', '1L') } [1] 1 -##com.oracle.truffle.r.test.library.fastr.TestInteropEval.testInteropEval +##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval #if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { .fastr.interop.eval('application/x-r', 'TRUE') } [1] TRUE -##com.oracle.truffle.r.test.library.fastr.TestInteropEval.testInteropEval +##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval #if (length(grep("FastR", R.Version()$version.string)) != 1) { as.character(123) } else { .fastr.interop.eval('application/x-r', 'as.character(123)') } [1] "123" +##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport +#if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', 'foo') } + +##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport +#if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', 14 + 2) } + +##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport +#if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', 1:100) } + +##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) { 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 +[1] 1 + +$longValue +[1] 123412341234 + +$charValue +[1] "R" + +$shortValue +[1] -100 + +$booleanValue +[1] TRUE + +$stringValue +[1] "foo" + +attr(,"is.truffle.object") +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 -5 199\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { v <- .fastr.interop.import('testIntArray'); print(v) } +[1] 1 -5 199 +attr(,"is.truffle.object") +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 -5 199\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { v <- .fastr.interop.import('testIntArray'); v } +[1] 1 -5 199 +attr(,"is.truffle.object") +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "" "foo"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { v <- .fastr.interop.import('testStringArray'); print(v) } +[1] "a" "" "foo" +attr(,"is.truffle.object") +[1] TRUE + ##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 @@ -110250,6 +112331,42 @@ In qnorm(c(0.1, 0.9, 0.5, 1.00001, 0.99999), 100, c(20, 1)) : NaNs produced #{ round(100*sd(c(1,2))^2) } [1] 50 +##com.oracle.truffle.r.test.library.stats.TestUpdateForm.basicTests +#update.formula(. ~ u+v, log(.) ~ .:q) +log(.) ~ u:q + v:q + +##com.oracle.truffle.r.test.library.stats.TestUpdateForm.basicTests +#update.formula(. ~ u+v, x + . ~ y:. + log(.)) +x + . ~ log(u + v) + y:u + y:v + +##com.oracle.truffle.r.test.library.stats.TestUpdateForm.basicTests +#update.formula(. ~ u+v, ~ . + x2) +. ~ u + v + x2 + +##com.oracle.truffle.r.test.library.stats.TestUpdateForm.basicTests +#update.formula(x ~ u+v, log(.) ~ .:q) +log(x) ~ u:q + v:q + +##com.oracle.truffle.r.test.library.stats.TestUpdateForm.basicTests +#update.formula(x ~ u+v, x + . ~ y:. + log(.)) +x + x ~ log(u + v) + y:u + y:v + +##com.oracle.truffle.r.test.library.stats.TestUpdateForm.basicTests +#update.formula(x ~ u+v, ~ . + x2) +x ~ u + v + x2 + +##com.oracle.truffle.r.test.library.stats.TestUpdateForm.basicTests +#update.formula(x ~ y, log(.) ~ .:q) +log(x) ~ y:q + +##com.oracle.truffle.r.test.library.stats.TestUpdateForm.basicTests +#update.formula(x ~ y, x + . ~ y:. + log(.)) +x + x ~ y + log(y) + +##com.oracle.truffle.r.test.library.stats.TestUpdateForm.basicTests +#update.formula(x ~ y, ~ . + x2) +x ~ y + x2 + ##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) @@ -110396,6 +112513,38 @@ Tracing f(100) on entry [1] 100 NULL +##com.oracle.truffle.r.test.library.utils.TestTypeConvert.basicTests +#type.convert('-2147483648') +[1] -2147483648 + +##com.oracle.truffle.r.test.library.utils.TestTypeConvert.basicTests +#type.convert('42') +[1] 42 + +##com.oracle.truffle.r.test.library.utils.TestTypeConvert.basicTests +#type.convert(c('42', '42.42')) +[1] 42.00 42.42 + +##com.oracle.truffle.r.test.library.utils.TestTypeConvert.basicTests +#type.convert(c('NA', '42')) +[1] NA 42 + +##com.oracle.truffle.r.test.library.utils.TestTypeConvert.basicTests +#type.convert(c('NA', '44.5')) +[1] NA 44.5 + +##com.oracle.truffle.r.test.library.utils.TestTypeConvert.basicTests +#type.convert(c('NA', 'NA')) +[1] NA NA + +##com.oracle.truffle.r.test.library.utils.TestTypeConvert.basicTests +#type.convert(c('NA', 'TRUE')) +[1] NA TRUE + +##com.oracle.truffle.r.test.library.utils.TestTypeConvert.basicTests +#type.convert(c(NA, '44.5')) +[1] NA 44.5 + ##com.oracle.truffle.r.test.library.utils.TestUtils.testHeadNTail #{head(letters)} [1] "a" "b" "c" "d" "e" "f" @@ -110446,6 +112595,27 @@ NULL [28] plot.tskernel* plot.TukeyHSD* see '?methods' for accessing help and source code +##com.oracle.truffle.r.test.library.utils.TestWriteTable.testTable +#write.table(data.frame(col=c(1,2,3,4), col2=c(T, F, T, F))) +"col" "col2" +"1" 1 TRUE +"2" 2 FALSE +"3" 3 TRUE +"4" 4 FALSE + +##com.oracle.truffle.r.test.library.utils.TestWriteTable.testValuesFormatting +#write.csv(data.frame(col=as.factor(c('m', 'm', 'f', 'm')))) +"","col" +"1","m" +"2","m" +"3","f" +"4","m" + +##com.oracle.truffle.r.test.library.utils.TestWriteTable.testValuesFormatting +#write.csv(data.frame(double=1231231234.5, bool=TRUE, raw=as.raw(42))) +"","double","bool","raw" +"1",1231231234.5,TRUE,2a + ##com.oracle.truffle.r.test.parser.TestParser.testLexerError #%0 Error: unexpected input in "%0" @@ -110542,7 +112712,7 @@ Error: unexpected '*' in: [7] 0.35201276 0.16919220 0.93579263 0.26084486 ##com.oracle.truffle.r.test.rpackages.TestRFFIPackage.testLoadTestRFFIDotC -#{ library("testrffi", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r1 <- rffi.dotCModifiedArguments(c(0,1,2,3)); r1 } +#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r1 <- rffi.dotCModifiedArguments(c(0,1,2,3)); r1 } [[1]] [1] 4 @@ -110557,7 +112727,7 @@ Error: unexpected '*' in: ##com.oracle.truffle.r.test.rpackages.TestRFFIPackage.testLoadTestRFFIExternal -#{ library("testrffi", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r1 <- rffi.dotExternalAccessArgs(1L, 3, c(1,2,3), c('a', 'b'), 'b', TRUE, as.raw(12)); detach("package:testrffi"); r1 } +#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r1 <- rffi.dotExternalAccessArgs(1L, 3, c(1,2,3), c('a', 'b'), 'b', TRUE, as.raw(12)); detach("package:testrffi"); r1 } [[1]] [[1]][[1]] NULL @@ -110616,7 +112786,7 @@ NULL ##com.oracle.truffle.r.test.rpackages.TestRFFIPackage.testLoadTestRFFIExternalWithNames -#{ library("testrffi", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r1 <- rffi.dotExternalAccessArgs(x=1L, 3, c(1,2,3), y=c('a', 'b'), 'b', TRUE, as.raw(12)); detach("package:testrffi"); r1 } +#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r1 <- rffi.dotExternalAccessArgs(x=1L, 3, c(1,2,3), y=c('a', 'b'), 'b', TRUE, as.raw(12)); detach("package:testrffi"); r1 } [[1]] [[1]][[1]] x @@ -110675,11 +112845,11 @@ NULL ##com.oracle.truffle.r.test.rpackages.TestRFFIPackage.testLoadTestRFFIManyArgs -#{ library("testrffi", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r1 <- rffi.invoke12(); detach("package:testrffi"); r1 } +#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r1 <- rffi.invoke12(); detach("package:testrffi"); r1 } [1] 12 ##com.oracle.truffle.r.test.rpackages.TestRFFIPackage.testLoadTestRFFISimple -#{ library("testrffi", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); c3 <- c(1L,2L,3L); r1 <- rffi.iterate_iarray(c3); r2 <- rffi.iterate_iptr(c3); detach("package:testrffi"); list(r1, r2) } +#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); c3 <- c(1L,2L,3L); r1 <- rffi.iterate_iarray(c3); r2 <- rffi.iterate_iptr(c3); detach("package:testrffi"); list(r1, r2) } [[1]] [1] 1 2 3 @@ -110688,7 +112858,7 @@ NULL ##com.oracle.truffle.r.test.rpackages.TestRFFIPackage.testLoadTestRFFISimple -#{ library("testrffi", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r1 <- rffi.addInt(2L, 3L); r2 <- rffi.addDouble(2, 3); r3 <- rffi.populateIntVector(5); r4 <- rffi.populateLogicalVector(5); detach("package:testrffi"); list(r1, r2, r3, r4) } +#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r1 <- rffi.addInt(2L, 3L); r2 <- rffi.addDouble(2, 3); r3 <- rffi.populateIntVector(5); r4 <- rffi.populateLogicalVector(5); detach("package:testrffi"); list(r1, r2, r3, r4) } [[1]] [1] 5 @@ -110703,7 +112873,7 @@ NULL ##com.oracle.truffle.r.test.rpackages.TestRFFIPackage.testLoadTestRFFISimple -#{ library("testrffi", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r1 <- rffi.mkStringFromChar(); r2 <- rffi.mkStringFromBytes(); r3 <- rffi.null(); r4 <-rffi.isRString(character(0)); detach("package:testrffi"); list(r1, r2, r3, r4) } +#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r1 <- rffi.mkStringFromChar(); r2 <- rffi.mkStringFromBytes(); r3 <- rffi.null(); r4 <-rffi.isRString(character(0)); detach("package:testrffi"); list(r1, r2, r3, r4) } [[1]] [1] "hello" @@ -110718,58 +112888,58 @@ NULL ##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad -#{ library(KernSmooth, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:KernSmooth"); } +#{ 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 -#{ library(MASS, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:MASS"); } +#{ library(MASS, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:MASS"); } ##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad -#{ library(Matrix, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:Matrix"); } +#{ library(Matrix, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:Matrix"); } ##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad -#{ library(boot, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:boot"); } +#{ library(boot, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:boot"); } ##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad -#{ library(class, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:class"); } +#{ library(class, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:class"); } ##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad -#{ library(cluster, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:cluster"); } +#{ library(cluster, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:cluster"); } ##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad -#{ library(codetools, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:codetools"); } +#{ library(codetools, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:codetools"); } ##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad -#{ library(foreign, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:foreign"); } +#{ library(foreign, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:foreign"); } ##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad -#{ library(lattice, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:lattice"); } +#{ library(lattice, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:lattice"); } ##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad -#{ library(nlme, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:nlme"); } +#{ library(nlme, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:nlme"); } ##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad -#{ library(nnet, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:nnet"); } +#{ library(nnet, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:nnet"); } ##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad -#{ library(rpart, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:rpart"); } +#{ library(rpart, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:rpart"); } ##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad -#{ library(spatial, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:spatial"); } +#{ library(spatial, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:spatial"); } ##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad -#{ library(survival, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:survival"); } +#{ 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 = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r<-print(tests4:::inspect.vehicle(new("Car"), new("Inspector"))); detach("package:tests4"); unloadNamespace("tests4"); r } +#{ 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 = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r<-print(tests4:::inspect.vehicle(new("Car"), new("StateInspector"))); detach("package:tests4"); unloadNamespace("tests4"); r } +#{ 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 @@ -110777,32 +112947,32 @@ NULL NULL ##com.oracle.truffle.r.test.rpackages.TestS4TestPackage.testS4Execute -#{ library("tests4", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r<-print(tests4:::inspect.vehicle(new("Truck"), new("Inspector"))); detach("package:tests4"); unloadNamespace("tests4"); r } +#{ 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 = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r<-print(tests4:::inspect.vehicle(new("Truck"), new("StateInspector"))); detach("package:tests4"); unloadNamespace("tests4"); r } +#{ 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 = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:tests4"); unloadNamespace("tests4") } +#{ 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 = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r <- vanilla(); detach("package:vanilla"); r } +#{ 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 = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r<-42; vanilla::foo(r)<-7; detach("package:vanilla"); r } +#{ 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 = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r <- functionTest(c(1,2,3,4,5,6),8:10); detach("package:vanilla"); r } +#{ 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/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java index d903558850aaac15c22318a819ca6b86323b9df3..41a29e7c30c60c0d76f902975ed2a4fa92aba4e6 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 @@ -112,6 +112,15 @@ public class TestS4 extends TestRBase { } + @Test + public void testStdGeneric() { + assertEval("{ standardGeneric(42) }"); + assertEval("{ standardGeneric(character()) }"); + assertEval("{ standardGeneric(\"\") }"); + assertEval("{ standardGeneric(\"foo\", 42) }"); + assertEval("{ x<-42; class(x)<-character(); standardGeneric(\"foo\", x) }"); + } + @Override public String getTestDir() { return "S4"; 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 7b40db76e668e950a4a887f015dafb093c931042..29d679be128ad94a376e3e106dc5e312d0aca53e 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 @@ -37,8 +37,8 @@ import org.junit.Test; import org.junit.runner.Description; import org.junit.runner.Result; +import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RPerfStats; import com.oracle.truffle.r.runtime.ResourceHandlerFactory; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.context.ContextInfo; @@ -129,8 +129,13 @@ public class TestBase { private static final String EXPECTED = "expected="; private static final String GEN_FASTR = "gen-fastr="; private static final String GEN_DIFFS = "gen-diff="; - private static final String KEEP_TRAILING_WHITESPACEG = "keep-trailing-whitespace"; + private static final String KEEP_TRAILING_WHITESPACE = "keep-trailing-whitespace"; + private static final String TRACE_TESTS = "trace-tests"; private static final String TEST_METHODS = "test-methods="; + /** + * The dir where 'mx' puts the output from building this project. + */ + private static final String TEST_PROJECT_OUTPUT_DIR = "test-project-output-dir="; private final String arg; @@ -164,8 +169,12 @@ public class TestBase { genExpectedQuiet = true; } else if (directive.equals(CHECK_EXPECTED)) { checkExpected = true; - } else if (directive.equals(KEEP_TRAILING_WHITESPACEG)) { + } else if (directive.equals(KEEP_TRAILING_WHITESPACE)) { keepTrailingWhiteSpace = true; + } else if (directive.equals(TRACE_TESTS)) { + traceTests = true; + } else if (directive.startsWith(TEST_PROJECT_OUTPUT_DIR)) { + testProjectOutputDir = Paths.get(directive.replace(TEST_PROJECT_OUTPUT_DIR, "")); } else if (directive.equals(TEST_METHODS)) { testMethodsPattern = directive.replace(TEST_METHODS, ""); } else { @@ -178,6 +187,7 @@ public class TestBase { } expectedOutputManager = new ExpectedTestOutputManager(expectedOutputFile, genExpected, checkExpected, genExpectedQuiet); fastROutputManager = new FastRTestOutputManager(fastROutputFile); + addOutputHook(); } catch (Throwable ex) { throw new AssertionError("R initialization failure", ex); } @@ -203,7 +213,6 @@ public class TestBase { if (diffsOutputFile != null) { TestOutputManager.writeDiffsTestOutputFile(diffsOutputFile, expectedOutputManager, fastROutputManager); } - RPerfStats.report(); } catch (IOException ex) { throw new RuntimeException(ex); } @@ -213,15 +222,25 @@ public class TestBase { @Override public void testStarted(Description description) { testElementName = description.getClassName() + "." + description.getMethodName(); + if (traceTests) { + System.out.println(testElementName); + } failedMicroTests = new ArrayList<>(); } } @Before public void beforeTest() { + checkOutputManagersInitialized(); + } + + private static void checkOutputManagersInitialized() { if (expectedOutputManager == null) { - // assume we are running a unit test in an IDE and the RunListener was not invoked. - // In this case we can expect the test output file to exist and open it as a resource + /* + * Assume we are running a unit test in an IDE/non-JUnit setup and therefore the + * RunListener was not invoked. In this case we can expect the test output file to exist + * and open it as a resource. + */ URL expectedTestOutputURL = ResourceHandlerFactory.getHandler().getResource(TestBase.class, TestOutputManager.TEST_EXPECTED_OUTPUT_FILE); if (expectedTestOutputURL == null) { Assert.fail("cannot find " + TestOutputManager.TEST_EXPECTED_OUTPUT_FILE + " resource"); @@ -229,6 +248,7 @@ public class TestBase { try { expectedOutputManager = new ExpectedTestOutputManager(new File(expectedTestOutputURL.getPath()), false, false, false); fastROutputManager = new FastRTestOutputManager(null); + addOutputHook(); } catch (IOException ex) { Assert.fail("error reading: " + expectedTestOutputURL.getPath() + ": " + ex); } @@ -236,6 +256,33 @@ public class TestBase { } } + /** + * Method for non-JUnit implementation to emulate important behavior of {@link RunListener}. + */ + public static void emulateRunListener() { + checkOutputManagersInitialized(); + } + + /** + * Method for non-JUnit implementation to set test tracing. + */ + public static void setTraceTests() { + traceTests = true; + } + + /** + * Set the test context explicitly (for non-JUnit implementation). N.B. The {@code lineno} is + * not the micro-test line, but that of the method declaration. + */ + public void doBeforeTest(String className, int lineno, String methodName) { + testElementName = className + "." + methodName; + failedMicroTests = new ArrayList<>(); + explicitTestContext = String.format("%s:%d (%s)", className, lineno, methodName); + if (traceTests) { + System.out.println(testElementName); + } + } + private static class ExpectedTestOutputManager extends TestOutputManager { private final boolean generate; @@ -344,6 +391,13 @@ public class TestBase { */ private static boolean keepTrailingWhiteSpace; + /** + * Trace the test methods as they are executed (debugging). + */ + private static boolean traceTests; + + private static Path testProjectOutputDir; + protected static final String ERROR = "Error"; protected static final String WARNING = "Warning message"; @@ -415,14 +469,56 @@ public class TestBase { private static Path cwd; + private static Path getCwd() { + if (cwd == null) { + cwd = Paths.get(System.getProperty("user.dir")); + } + return cwd; + } + + public static void setTestProjectOutputDir(String path) { + testProjectOutputDir = Paths.get(path); + } + + private static final String TEST_OUTPUT = "tmptest"; + /** - * Return a path that is relative to the cwd when running tests. + * Return a path that is relative to the 'cwd/testoutput' when running tests. */ public static Path relativize(Path path) { - if (cwd == null) { - cwd = Paths.get(System.getProperty("user.dir")); + return getCwd().relativize(path); + } + + /** + * Creates a directory with suffix {@code name} in the {@code testoutput} directory and returns + * a relative path to it. + */ + public static Path createTestDir(String name) { + Path dir = Paths.get(getCwd().toString(), TEST_OUTPUT, name); + if (!dir.toFile().exists()) { + if (!dir.toFile().mkdirs()) { + Assert.fail("failed to create dir: " + dir.toString()); + } } - return cwd.relativize(path); + return relativize(dir); + } + + private static final String TEST_PROJECT = "com.oracle.truffle.r.test"; + private static final String TEST_NATIVE_PROJECT = "com.oracle.truffle.r.test.native"; + + /** + * Returns a path to {@code baseName}, assumed to be nested in {@link #testProjectOutputDir}. + * The path is return relativized to the cwd. + */ + public static Path getProjectFile(Path baseName) { + Path baseNamePath = Paths.get(TEST_PROJECT.replace('.', '/'), baseName.toString()); + Path result = relativize(testProjectOutputDir.resolve(baseNamePath)); + return result; + } + + public static Path getNativeProjectFile(Path baseName) { + Path path = Paths.get(TEST_NATIVE_PROJECT, baseName.toString()); + return path; } private static void microTestFailed() { @@ -440,18 +536,25 @@ public class TestBase { if (explicitTestContext != null) { return explicitTestContext; } - // We want the stack trace as if the JUnit test failed + // We want the stack trace as if the JUnit test failed. RuntimeException ex = new RuntimeException(); // The first method not in TestBase is the culprit StackTraceElement culprit = null; - for (StackTraceElement se : ex.getStackTrace()) { - if (!se.getClassName().endsWith("TestBase")) { - culprit = se; - break; + try { + // N.B. This may not always be available (AOT). + StackTraceElement[] stackTrace = ex.getStackTrace(); + for (int i = 0; i < stackTrace.length; i++) { + StackTraceElement se = stackTrace[i]; + if (!se.getClassName().endsWith("TestBase")) { + culprit = se; + break; + } } + String context = String.format("%s:%d (%s)", culprit.getClassName(), culprit.getLineNumber(), culprit.getMethodName()); + return context; + } catch (NullPointerException npe) { + return "no test context available"; } - String context = String.format("%s:%d (%s)", culprit.getClassName(), culprit.getLineNumber(), culprit.getMethodName()); - return context; } private void evalAndCompare(String[] inputs, TestTrait... traits) { @@ -508,7 +611,9 @@ public class TestBase { } else { failedInputCount++; microTestFailed(); - System.out.print('E'); + if (inputs.length > 1) { + System.out.print('E'); + } } allOk &= ok; afterMicroTest(); @@ -657,7 +762,8 @@ public class TestBase { try { String message = matcher.group("msg" + i); Matcher messageMatcher = warningMessagePattern.matcher(message); - assert messageMatcher.matches() : "unexpected format in warning message: " + message; + boolean messageMatches = messageMatcher.matches(); + assert messageMatches : "unexpected format in warning message: " + message; str.append(messageMatcher.group("m").trim()).append('|'); } catch (IllegalArgumentException e) { break; @@ -690,11 +796,11 @@ public class TestBase { * Evaluate {@code input} in FastR, returning all (virtual) console output that was produced. If * {@code nonShared} then this must evaluate in a new, non-shared, {@link RContext}. */ - protected static String fastREval(String input, ContextInfo contextInfo, boolean longTimeout) { + protected String fastREval(String input, ContextInfo contextInfo, boolean longTimeout) { microTestInfo.expression = input; String result; try { - result = fastROutputManager.fastRSession.eval(input, contextInfo, longTimeout); + result = fastROutputManager.fastRSession.eval(this, input, contextInfo, longTimeout); } catch (Throwable e) { String clazz; if (e instanceof RInternalError && e.getCause() != null) { @@ -724,6 +830,19 @@ public class TestBase { return expectedOutputManager.checkOnly; } + /** + * Used only for package installation to avoid explicitly using {@link ProcessBuilder}. Instead + * we go via the {@code system2} R function (which may call {@link ProcessBuilder} internally). + * + */ + protected static Object evalInstallPackage(String system2Command) throws Throwable { + if (generatingExpected()) { + return expectedOutputManager.getRSession().eval(null, system2Command, null, true); + } else { + return fastROutputManager.fastRSession.evalAsObject(null, system2Command, null, true); + } + } + /** * Evaluate expected output from {@code input}. By default the lookup is based on {@code input} * but can be overridden by providing a non-null {@code testIdOrNull}. @@ -764,6 +883,13 @@ public class TestBase { return TestOutputManager.join(arrays); } + /** + * Tests that require additional {@link PolyglotEngine} global symbols should override this, + * which will be called just prior to the evaluation. + */ + public void addPolyglotSymbols(@SuppressWarnings("unused") PolyglotEngine.Builder builder) { + } + private static final LocalDiagnosticHandler localDiagnosticHandler = new LocalDiagnosticHandler(); private static class LocalDiagnosticHandler implements TestOutputManager.DiagnosticHandler { @@ -794,7 +920,7 @@ public class TestBase { protected static boolean deleteDir(Path dir) { try { Files.walkFileTree(dir, DELETE_VISITOR); - } catch (Exception e) { + } catch (Throwable e) { return false; } return true; @@ -820,7 +946,7 @@ public class TestBase { private static final DeleteVisitor DELETE_VISITOR = new DeleteVisitor(); - static { + private static void addOutputHook() { Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestRBase.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestRBase.java index bb429d6d972b0c9271939389be68c0cfc1f28298..c3e3ee014015f9dca26c83386d2265b0c686bd61 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestRBase.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestRBase.java @@ -33,22 +33,18 @@ import java.nio.file.Paths; import org.junit.Assert; import org.junit.Test; -import com.oracle.truffle.r.runtime.REnvVars; - -/* - * Base class for all Java test suites (in the sense of JUnit Java files) - * that want to run R tests stored in the file system as R sources. - * It is expected that R test source files will be stored in the R sub-directory - * of a directory stored in com.oracle.truffle.r.test/src/com/oracle/truffle/r/test +/** + * Base class for all Java test suites (in the sense of JUnit Java files) that want to run R tests + * stored in the file system as R sources. It is expected that R test source files will be stored in + * the R sub-directory of the {@code com.oracle.truffle.r.test} project. * - * The first line of the file may contain some configuration information (as an R comment). - * At this point, two keywords are recognized - ContainsError and ContansWarning. Including - * any of them on in the first line will cause appropriate execution method to be chosen - * (if both are present then ContainsError has precedence). + * The first line of the file may contain some configuration information (as an R comment). At this + * point, two keywords are recognized - ContainsError and ContansWarning. Including any of them on + * in the first line will cause appropriate execution method to be chosen (if both are present then + * ContainsError has precedence). * - * The R files are sourced, so any test results have to be explicitly printed. + * The R files are sourced, so any test results have to be explicitly printed. */ - public class TestRBase extends TestBase { /* @@ -64,7 +60,7 @@ public class TestRBase extends TestBase { if (testDirName == null) { return; } - Path testDirPath = Paths.get(REnvVars.rHome(), "com.oracle.truffle.r.test", "src", "com", "oracle", "truffle", "r", "test", testDirName, "R"); + Path testDirPath = TestBase.getProjectFile(Paths.get(testDirName, "R")); if (!Files.exists(testDirPath) || !Files.isDirectory(testDirPath)) { return; } @@ -91,7 +87,7 @@ public class TestRBase extends TestBase { } } bf.close(); - String testFilePath = TestBase.relativize(testDirPath.resolve(files[i].getName())).toString(); + String testFilePath = testDirPath.resolve(files[i].getName()).toString(); if (testTrait == null) { assertEval(TestBase.template("{ source(\"%0\") }", new String[]{testFilePath})); } else { diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Arg.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Arg.java index b896511b8833f3340b3379e43e54cb3fb7500ce2..0568155a691128eb8b1e2ec9aa2194202d41d821 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Arg.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Arg.java @@ -19,38 +19,36 @@ public class TestBuiltin_Arg extends TestBase { @Test public void testArg1() { - assertEval(Ignored.Unknown, "argv <- list(1+2i);Arg(argv[[1]]);"); + assertEval("argv <- list(1+2i);Arg(argv[[1]]);"); } @Test public void testArg2() { - assertEval(Ignored.Unknown, - "argv <- list(c(1554.86976865791+337.57296578684i, 1953.0195914094+434.16395869265i, 2020.8001333202+267.40279521531i, 12019.4947666225+397.6223289386i, 40989.2104557418+1079.1450107273i, 59779.5384921205+1460.5074297272i, 40703.4141691824+1049.8100128697i, 12234.4562968499+469.0052365648i, 2311.58538965355+142.56529231224i, 2158.93441543181+94.80017111005i, 2768.79882180339+256.05759156168i, 3234.20673958634+282.64174433659i, 2796.76248579155+64.23534085425i, 2030.22757739534-164.56566766766i, 1522.09271008314-273.51503749101i, 1109.23177636373-215.24298332377i, 714.154122222449-75.284630456206i, 509.684427096512-24.577531288476i, 628.214718823948+42.431050163574i, 1053.2295477549+190.4802567974i, 1388.73708931304+133.04405268816i, 1213.97041311196-135.67196064028i, 790.469479873384-232.737914916798i, 503.424076694357-99.275737105817i, 430.214847703846+45.250156289826i, 640.795334515383+121.961327286573i, 794.927869993865+100.643091831764i, 554.394621183915-15.753680159958i, 286.476583987294-104.634488576316i, 232.82067569803-92.469328935268i, 229.472155078088-54.85406188579i, 253.438957119958-65.123390974834i, 285.141954428461-79.653095359009i, 257.168942241366-34.332533775171i, 214.215071612655+18.001149572355i, 199.882436088191+0i));Arg(argv[[1]]);"); + assertEval("argv <- list(c(1554.86976865791+337.57296578684i, 1953.0195914094+434.16395869265i, 2020.8001333202+267.40279521531i, 12019.4947666225+397.6223289386i, 40989.2104557418+1079.1450107273i, 59779.5384921205+1460.5074297272i, 40703.4141691824+1049.8100128697i, 12234.4562968499+469.0052365648i, 2311.58538965355+142.56529231224i, 2158.93441543181+94.80017111005i, 2768.79882180339+256.05759156168i, 3234.20673958634+282.64174433659i, 2796.76248579155+64.23534085425i, 2030.22757739534-164.56566766766i, 1522.09271008314-273.51503749101i, 1109.23177636373-215.24298332377i, 714.154122222449-75.284630456206i, 509.684427096512-24.577531288476i, 628.214718823948+42.431050163574i, 1053.2295477549+190.4802567974i, 1388.73708931304+133.04405268816i, 1213.97041311196-135.67196064028i, 790.469479873384-232.737914916798i, 503.424076694357-99.275737105817i, 430.214847703846+45.250156289826i, 640.795334515383+121.961327286573i, 794.927869993865+100.643091831764i, 554.394621183915-15.753680159958i, 286.476583987294-104.634488576316i, 232.82067569803-92.469328935268i, 229.472155078088-54.85406188579i, 253.438957119958-65.123390974834i, 285.141954428461-79.653095359009i, 257.168942241366-34.332533775171i, 214.215071612655+18.001149572355i, 199.882436088191+0i));Arg(argv[[1]]);"); } @Test public void testArg3() { - assertEval(Ignored.Unknown, - "argv <- list(c(-12.561836573133-726.935211685406i, -19.15961591777-1315.40822424617i, -666.84872452586-2013.90899841237i, -5775.9038598237-11495.8986046958i, -19052.0606820086-36788.5714510618i, -27954.209922899-52600.8398855356i, -19930.6456597181-35739.3494902644i, -7168.9170917163-10787.9325286278i, -2331.00733468417-1545.77448035635i, -1953.77845230855-212.90200115993i, -1953.60071030304+1420.43983282655i, -1700.4015174326+2765.31423009739i, -862.10275212019+2693.95914108523i, 163.24691179114+1837.1971341258i, 824.29498680332+1155.03126302727i, 939.495937605926+679.549172893055i, 686.101881005818+305.166761591578i, 460.339323160381-14.067413050801i, 533.688543397269-293.997358985575i, 773.041200043657-698.096300485637i, 716.84959340189-1127.39175172066i, 226.23728166311-1110.40349894929i, -203.687633095422-740.924670781257i, -271.865544904439-437.858153233594i, -316.769706633022-279.671035520361i, -624.842102639273-228.211019456587i, -806.31350008813-164.912647906911i, -506.559675826232+24.376187336594i, -142.784303570554+217.087547410547i, -44.704338624059+260.225831716256i, 10.565037460572+219.942519605707i, 143.643627814428+218.823069474359i, 232.58540850813+214.905815487636i, 223.286482103748+175.139821578561i, 185.008902762186+116.519845434485i, 171.150234739785-0i));Arg(argv[[1]]);"); + assertEval("argv <- list(c(-12.561836573133-726.935211685406i, -19.15961591777-1315.40822424617i, -666.84872452586-2013.90899841237i, -5775.9038598237-11495.8986046958i, -19052.0606820086-36788.5714510618i, -27954.209922899-52600.8398855356i, -19930.6456597181-35739.3494902644i, -7168.9170917163-10787.9325286278i, -2331.00733468417-1545.77448035635i, -1953.77845230855-212.90200115993i, -1953.60071030304+1420.43983282655i, -1700.4015174326+2765.31423009739i, -862.10275212019+2693.95914108523i, 163.24691179114+1837.1971341258i, 824.29498680332+1155.03126302727i, 939.495937605926+679.549172893055i, 686.101881005818+305.166761591578i, 460.339323160381-14.067413050801i, 533.688543397269-293.997358985575i, 773.041200043657-698.096300485637i, 716.84959340189-1127.39175172066i, 226.23728166311-1110.40349894929i, -203.687633095422-740.924670781257i, -271.865544904439-437.858153233594i, -316.769706633022-279.671035520361i, -624.842102639273-228.211019456587i, -806.31350008813-164.912647906911i, -506.559675826232+24.376187336594i, -142.784303570554+217.087547410547i, -44.704338624059+260.225831716256i, 10.565037460572+219.942519605707i, 143.643627814428+218.823069474359i, 232.58540850813+214.905815487636i, 223.286482103748+175.139821578561i, 185.008902762186+116.519845434485i, 171.150234739785-0i));Arg(argv[[1]]);"); } @Test public void testArg4() { - assertEval(Ignored.Unknown, "argv <- list(logical(0));Arg(argv[[1]]);"); + assertEval("argv <- list(logical(0));Arg(argv[[1]]);"); } @Test public void testArg5() { - assertEval(Ignored.Unknown, "argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));Arg(argv[[1]]);"); + assertEval("argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));Arg(argv[[1]]);"); } @Test public void testArg6() { - assertEval(Ignored.Unknown, "argv <- list(FALSE);Arg(argv[[1]]);"); + assertEval("argv <- list(FALSE);Arg(argv[[1]]);"); } @Test public void testArg8() { - assertEval(Ignored.Unknown, "argv <- list(-1);do.call('Arg', argv)"); + assertEval("argv <- list(-1);do.call('Arg', argv)"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Conj.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Conj.java index baf1db1236887f839e7e7ed45fe3f2689aba62a5..2835d7fbe9da44b959434f734aca29358042afbd 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Conj.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Conj.java @@ -34,8 +34,7 @@ public class TestBuiltin_Conj extends TestBase { @Test public void testConj4() { - assertEval(Ignored.Unknown, - "argv <- list(c(1+0i, 0.985449458355365-0.138495889434283i, 0.942642872008266-0.270298493966801i, 0.874055380411015-0.389154527907249i, 0.783616834775482-0.489658143691394i, 0.676434265976222-0.567595743096322i, 0.558433187362516-0.620202886580765i, 0.435944803381395-0.646314749919218i, 0.315270204563124-0.646399711551264i, 0.202254248593737-0.622474571220695i, 0.101900933636988-0.577908912337521i, 0.018058735786294-0.517134531945579i, -0.046801131817278-0.445283024979697i, -0.091697846014566-0.367779972441526i, -0.117138246792619-0.289927334668645i, -0.125-0.21650635094611i, -0.118311211562746-0.151431445234362i, -0.1009450259937-0.097481478474725i, -0.0772542485937368-0.0561284970724482i, -0.0516755705617768-0.027476388254185i, -0.0283351996132097-0.0103131692411995i, -0.0106874359562526-0.0022716846399295i, -1.21500794451954e-03-8.496163204619e-05i, -1.21500794451956e-03+8.49616320463e-05i, -0.0106874359562525+0.0022716846399297i, -0.0283351996132096+0.0103131692411996i, -0.0516755705617767+0.0274763882541851i, -0.0772542485937367+0.0561284970724481i, -0.1009450259937+0.097481478474725i, -0.118311211562746+0.151431445234362i, -0.125+0.21650635094611i, -0.117138246792619+0.289927334668644i, -0.091697846014566+0.367779972441526i, -0.046801131817278+0.445283024979697i, 0.018058735786294+0.517134531945579i, 0.101900933636988+0.577908912337521i, 0.202254248593737+0.622474571220695i, 0.315270204563124+0.646399711551264i, 0.435944803381395+0.646314749919218i, 0.558433187362516+0.620202886580765i, 0.676434265976221+0.567595743096322i, 0.783616834775482+0.489658143691394i, 0.874055380411015+0.389154527907249i, 0.942642872008266+0.270298493966801i, 0.985449458355365+0.138495889434283i));Conj(argv[[1]]);"); + assertEval("argv <- list(c(1+0i, 0.985449458355365-0.138495889434283i, 0.942642872008266-0.270298493966801i, 0.874055380411015-0.389154527907249i, 0.783616834775482-0.489658143691394i, 0.676434265976222-0.567595743096322i, 0.558433187362516-0.620202886580765i, 0.435944803381395-0.646314749919218i, 0.315270204563124-0.646399711551264i, 0.202254248593737-0.622474571220695i, 0.101900933636988-0.577908912337521i, 0.018058735786294-0.517134531945579i, -0.046801131817278-0.445283024979697i, -0.091697846014566-0.367779972441526i, -0.117138246792619-0.289927334668645i, -0.125-0.21650635094611i, -0.118311211562746-0.151431445234362i, -0.1009450259937-0.097481478474725i, -0.0772542485937368-0.0561284970724482i, -0.0516755705617768-0.027476388254185i, -0.0283351996132097-0.0103131692411995i, -0.0106874359562526-0.0022716846399295i, -1.21500794451954e-03-8.496163204619e-05i, -1.21500794451956e-03+8.49616320463e-05i, -0.0106874359562525+0.0022716846399297i, -0.0283351996132096+0.0103131692411996i, -0.0516755705617767+0.0274763882541851i, -0.0772542485937367+0.0561284970724481i, -0.1009450259937+0.097481478474725i, -0.118311211562746+0.151431445234362i, -0.125+0.21650635094611i, -0.117138246792619+0.289927334668644i, -0.091697846014566+0.367779972441526i, -0.046801131817278+0.445283024979697i, 0.018058735786294+0.517134531945579i, 0.101900933636988+0.577908912337521i, 0.202254248593737+0.622474571220695i, 0.315270204563124+0.646399711551264i, 0.435944803381395+0.646314749919218i, 0.558433187362516+0.620202886580765i, 0.676434265976221+0.567595743096322i, 0.783616834775482+0.489658143691394i, 0.874055380411015+0.389154527907249i, 0.942642872008266+0.270298493966801i, 0.985449458355365+0.138495889434283i));Conj(argv[[1]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Encoding.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Encoding.java index e240f384ac98453d7ee2320c9378d34156a50bcb..2fd0304038b7ca57b8c5b2797348b8fdc49f3451 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Encoding.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Encoding.java @@ -58,4 +58,9 @@ public class TestBuiltin_Encoding extends TestBase { public void testEncoding9() { assertEval("argv <- structure(list(x = 'abc'), .Names = 'x');do.call('Encoding', argv)"); } + + @Test + public void testEncoding() { + assertEval("{ x<-42; Encoding(x) }"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Encodingassign_.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Encodingassign_.java index 0d80cab584563cbbcc0bae271e8d8ae3b2cad33e..1ec1d428fc74771914f817979a7d277bb032a0ec 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Encodingassign_.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Encodingassign_.java @@ -22,4 +22,13 @@ public class TestBuiltin_Encodingassign_ extends TestBase { public void testEncodingassign_1() { assertEval("argv <- structure(list(x = 'abc', value = 'UTF-8'), .Names = c('x', 'value'));do.call('Encoding<-', argv)"); } + + @Test + public void testEncoding() { + assertEval(Output.IgnoreErrorContext, "{ x<-42; Encoding(x)<-\"UTF-8\" }"); + assertEval(Output.IgnoreErrorContext, "{ x<-\"foo\"; Encoding(x)<-NULL }"); + assertEval(Output.IgnoreErrorContext, "{ x<-\"foo\"; Encoding(x)<-42 }"); + assertEval(Output.IgnoreErrorContext, "{ x<-\"foo\"; Encoding(x)<-character() }"); + } + } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Im.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Im.java index 82b42bc317582c0e660d61da379f5886f9e56dd3..76738ecfa18a5b432ee11fb4be04bff5fca7952d 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Im.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Im.java @@ -62,5 +62,8 @@ public class TestBuiltin_Im extends TestBase { assertEval("{ x <- c(1+2i,3-4i) ; attr(x,\"my\") <- 2 ; Im(x) }"); assertEval("{ Im(as.raw(12)) }"); + + assertEval(Ignored.ImplementationError, "Im(c(NaN, 1+1i))"); + assertEval("Im(NaN)"); } } 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 1adbab4d3488259a6618c7dd8945dad05fc54f0c..abb33a5090399709a83438d76f770b4fb2de1214 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 @@ -29,11 +29,16 @@ public class TestBuiltin_La extends TestBase { } @Test - public void testLa3() { + public void testLa3a() { assertEval(Ignored.Unknown, "argv <- list(structure(c(-21.2222451396881, 306.936914624821, 0, 0, 0, -101.353437863947, -21.2222451396881, 0, 0, 0, 45.8768670002026, 63.2672432400162, -11.7486843755171, 0, 0, 65.1621918666428, 125.787781278037, -111.869521123473, 61.0965873274467, -54.389932439947, -26.0785375270079, -209.347244886481, 112.817924425406, 108.385517228532, 61.0965873274467), .Dim = c(5L, 5L), .Dimnames = list(NULL, NULL)), FALSE); .Internal(La_rg(argv[[1]], argv[[2]]))"); } + @Test + public void testLa3b() { + assertEval("argv <- list(structure(c(-21.2222451396881, 306.936914624821, 0, 0, 0, -101.353437863947, -21.2222451396881, 0, 0, 0, 45.8768670002026, 63.2672432400162, -11.7486843755171, 0, 0, 65.1621918666428, 125.787781278037, -111.869521123473, 61.0965873274467, -54.389932439947, -26.0785375270079, -209.347244886481, 112.817924425406, 108.385517228532, 61.0965873274467), .Dim = c(5L, 5L), .Dimnames = list(NULL, NULL)), TRUE); .Internal(La_rg(argv[[1]], argv[[2]]))"); + } + @Test public void testLa4() { assertEval(Ignored.Unknown, @@ -72,5 +77,8 @@ public class TestBuiltin_La extends TestBase { @Test public void testMisc() { assertEval("{ x<-matrix(1:4, ncol=2); solve(x) }"); + assertEval("{ .Internal(La_solve(structure(numeric(0), .Dim = c(0,0)), structure(c(1, 0, 0, 1), .Dim = c(2L, 2L)), 2.22044604925031e-16)) }"); + assertEval("{ .Internal(La_solve(structure(c(2,1), .Dim = c(2,1)), structure(c(1, 0, 0, 1), .Dim = c(2L, 2L)), 2.22044604925031e-16)) }"); + assertEval("{ .Internal(La_solve(structure(c(2,1)), structure(c(1, 0, 0, 1), .Dim = c(2L, 2L)), 2.22044604925031e-16)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Mod.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Mod.java index b9509fe23a40f70657261b7e872176b86a949ca1..32fdd8883b352f22a0c450a2f0436badb7f1016f 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Mod.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Mod.java @@ -46,6 +46,6 @@ public class TestBuiltin_Mod extends TestBase { public void testMod() { assertEval("{ round(Mod(1+1i)*10000) }"); assertEval("{ Mod(as.raw(12)) }"); - assertEval("{ is.integer(Mod(FALSE) }"); + assertEval("{ is.integer(Mod(FALSE)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Primitive.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Primitive.java index dd1cb83bac27a21d515b2dbc9d66231d545b9f4b..0a5be54776f6d0366f142b7175f1fc4fb3284c57 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Primitive.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Primitive.java @@ -19,6 +19,13 @@ public class TestBuiltin_Primitive extends TestBase { @Test public void testPrimitive1() { - assertEval(Ignored.Unknown, "argv <- list('c');.Primitive(argv[[1]]);"); + // our c() primitive is missing an argument + assertEval(Ignored.ImplementationError, "argv <- list('c');.Primitive(argv[[1]]);"); + + assertEval(".Primitive(c('c', 'b'))"); + assertEval(".Primitive('any')"); + assertEval(".Primitive('foo')"); + assertEval(".Primitive('complex')"); + assertEval(".Primitive(1)"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_RNGkind.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_RNGkind.java new file mode 100644 index 0000000000000000000000000000000000000000..4f797b4041b02226c776cb3b90df60803bdc6a99 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_RNGkind.java @@ -0,0 +1,40 @@ +/* + * 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.test.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestBuiltin_RNGkind extends TestBase { + @Test + public void testArgsCast() { + assertEval(".Internal(RNGkind(1L, 1L))"); + assertEval(".Internal(RNGkind(NULL, NULL))"); + // Note: GnuR casts 'abc' to int and then fails to find it, we do proper args validation in + // this case + assertEval(Output.IgnoreErrorMessage, ".Internal(RNGkind('abc', NULL))"); + // Note: GnuR also prints warning about NAs + assertEval(Output.IgnoreErrorMessage, ".Internal(RNGkind(NULL, 'abc'))"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Re.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Re.java index 26ce368ea0732d3e46063d439f89f6c8cbef3b6a..7eac103d968c9f9e2baac2e6176c20aa684b4c8d 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Re.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Re.java @@ -66,5 +66,8 @@ public class TestBuiltin_Re extends TestBase { assertEval("{ x <- c(1+2i,3-4i) ; attr(x,\"my\") <- 2 ; Re(x) }"); assertEval("{ Re(as.raw(12)) }"); + + assertEval(Ignored.ImplementationError, "Re(c(NaN, 1+1i))"); + assertEval("Re(NaN)"); } } 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 363b64538d0641b0bc3fae9f47d32ee89837faef..557d6a7a791d74c8b0a01c1a6f28793124f9b973 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 @@ -26,4 +26,11 @@ public class TestBuiltin_Syssetlocale extends TestBase { public void testSyssetlocale3() { assertEval("argv <- structure(list(category = 'LC_TIME', locale = 'C'), .Names = c('category', 'locale'));do.call('Sys.setlocale', argv)"); } + + @Test + public void testSyssetlocaleInvalidArgs() { + assertEval(Output.IgnoreErrorContext, ".Internal(Sys.setlocale(4, c('more', 'elements')))"); + assertEval(Output.IgnoreErrorContext, ".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_Syssleep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssleep.java index abe3abb0b30a816225d33129917a4e63b5a2e5df..1be9da224b58ad225bde4597f21c5e2031b028e0 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssleep.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssleep.java @@ -24,6 +24,6 @@ public class TestBuiltin_Syssleep extends TestBase { @Test public void testSyssleep2() { - assertEval(Ignored.Unknown, "argv <- list(FALSE); .Internal(Sys.sleep(argv[[1]]))"); + assertEval("argv <- list(FALSE); .Internal(Sys.sleep(argv[[1]]))"); } } 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 94a06282af26150926c508b62611ff4c73621548..65f3cd98aaf49d92c2043a2accc9aa9be0a2bfe4 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 @@ -152,6 +152,6 @@ public class TestBuiltin_abs extends TestBase { assertEval("{ abs(1:3) }"); assertEval("{ abs(-1:-3) }"); - assertEval("{ is.integer(abs(FALSE) }"); + assertEval("{ is.integer(abs(FALSE)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_acos.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_acos.java index 92c22e4ee63e7784f8bea6ce1f39a7a2e8cb3131..bcef99fcd20bff8d180911dacce59cac4f6fa485 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_acos.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_acos.java @@ -29,8 +29,7 @@ public class TestBuiltin_acos extends TestBase { @Test public void testacos3() { - assertEval(Ignored.Unknown, - "argv <- list(c(-0.7104065636993+1i, 0.25688370915653+1i, -0.24669187846237+1i, -0.34754259939773+1i, -0.95161856726502+1i, -0.04502772480892+1i, -0.78490446945708+1i, -1.66794193658814+1i, -0.38022652028776+1i, 0.91899660906077+1i, -0.57534696260839+1i, 0.60796432222503+1i, -1.61788270828916+1i, -0.05556196552454+1i, 0.51940720394346+1i, 0.30115336216671+1i, 0.10567619414894+1i, -0.64070600830538+1i, -0.84970434603358+1i, -1.02412879060491+1i, 0.11764659710013+1i, -0.9474746141848+1i, -0.49055744370067+1i, -0.25609219219825+1i, 1.84386200523221+1i, -0.65194990169546+1i, 0.23538657228486+1i, 0.07796084956371+1i, -0.96185663413013+1i, -0.0713080861236+1i, 1.44455085842335+1i, 0.45150405307921+1i, 0.04123292199294+1i, -0.42249683233962+1i, -2.05324722154052+1i, 1.13133721341418+1i, -1.46064007092482+1i, 0.73994751087733+1i, 1.90910356921748+1i, -1.4438931609718+1i, 0.70178433537471+1i, -0.26219748940247+1i, -1.57214415914549+1i, -1.51466765378175+1i, -1.60153617357459+1i, -0.5309065221703+1i, -1.4617555849959+1i, 0.68791677297583+1i, 2.10010894052567+1i, -1.28703047603518+1i, 0.78773884747518+1i, 0.76904224100091+1i, 0.33220257895012+1i, -1.00837660827701+1i, -0.11945260663066+1i, -0.28039533517025+1i, 0.56298953322048+1i, -0.37243875610383+1i, 0.97697338668562+1i, -0.37458085776701+1i, 1.05271146557933+1i, -1.04917700666607+1i, -1.26015524475811+1i, 3.2410399349424+1i, -0.41685758816043+1i, 0.29822759154072+1i, 0.63656967403385+1i, -0.48378062570874+1i, 0.51686204431361+1i, 0.36896452738509+1i, -0.21538050764169+1i, 0.06529303352532+1i, -0.03406725373846+1i, 2.12845189901618+1i, -0.74133609627283+1i, -1.09599626707466+1i, 0.03778839917108+1i, 0.31048074944314+1i, 0.43652347891018+1i, -0.45836533271111+1i, -1.06332613397119+1i, 1.26318517608949+1i, -0.34965038795355+1i, -0.86551286265337+1i, -0.2362795689411+1i, -0.19717589434855+1i, 1.10992028971364+1i, 0.0847372921972+1i, 0.75405378518452+1i, -0.49929201717226+1i, 0.2144453095816+1i, -0.32468591149083+1i, 0.09458352817357+1i, -0.89536335797754+1i, -1.31080153332797+1i, 1.99721338474797+1i, 0.60070882367242+1i, -1.25127136162494+1i, -0.61116591668042+1i, -1.18548008459731+1i));acos(argv[[1]]);"); + assertEval("argv <- list(c(-0.7104065636993+1i, 0.25688370915653+1i, -0.24669187846237+1i, -0.34754259939773+1i, -0.95161856726502+1i, -0.04502772480892+1i, -0.78490446945708+1i, -1.66794193658814+1i, -0.38022652028776+1i, 0.91899660906077+1i, -0.57534696260839+1i, 0.60796432222503+1i, -1.61788270828916+1i, -0.05556196552454+1i, 0.51940720394346+1i, 0.30115336216671+1i, 0.10567619414894+1i, -0.64070600830538+1i, -0.84970434603358+1i, -1.02412879060491+1i, 0.11764659710013+1i, -0.9474746141848+1i, -0.49055744370067+1i, -0.25609219219825+1i, 1.84386200523221+1i, -0.65194990169546+1i, 0.23538657228486+1i, 0.07796084956371+1i, -0.96185663413013+1i, -0.0713080861236+1i, 1.44455085842335+1i, 0.45150405307921+1i, 0.04123292199294+1i, -0.42249683233962+1i, -2.05324722154052+1i, 1.13133721341418+1i, -1.46064007092482+1i, 0.73994751087733+1i, 1.90910356921748+1i, -1.4438931609718+1i, 0.70178433537471+1i, -0.26219748940247+1i, -1.57214415914549+1i, -1.51466765378175+1i, -1.60153617357459+1i, -0.5309065221703+1i, -1.4617555849959+1i, 0.68791677297583+1i, 2.10010894052567+1i, -1.28703047603518+1i, 0.78773884747518+1i, 0.76904224100091+1i, 0.33220257895012+1i, -1.00837660827701+1i, -0.11945260663066+1i, -0.28039533517025+1i, 0.56298953322048+1i, -0.37243875610383+1i, 0.97697338668562+1i, -0.37458085776701+1i, 1.05271146557933+1i, -1.04917700666607+1i, -1.26015524475811+1i, 3.2410399349424+1i, -0.41685758816043+1i, 0.29822759154072+1i, 0.63656967403385+1i, -0.48378062570874+1i, 0.51686204431361+1i, 0.36896452738509+1i, -0.21538050764169+1i, 0.06529303352532+1i, -0.03406725373846+1i, 2.12845189901618+1i, -0.74133609627283+1i, -1.09599626707466+1i, 0.03778839917108+1i, 0.31048074944314+1i, 0.43652347891018+1i, -0.45836533271111+1i, -1.06332613397119+1i, 1.26318517608949+1i, -0.34965038795355+1i, -0.86551286265337+1i, -0.2362795689411+1i, -0.19717589434855+1i, 1.10992028971364+1i, 0.0847372921972+1i, 0.75405378518452+1i, -0.49929201717226+1i, 0.2144453095816+1i, -0.32468591149083+1i, 0.09458352817357+1i, -0.89536335797754+1i, -1.31080153332797+1i, 1.99721338474797+1i, 0.60070882367242+1i, -1.25127136162494+1i, -0.61116591668042+1i, -1.18548008459731+1i));acos(argv[[1]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_acosh.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_acosh.java index 301515288fde662c263e256352acd68bda1a30a4..123f2d9bf9ad59f3691bc8fe052b7c7cc281759d 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_acosh.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_acosh.java @@ -44,6 +44,6 @@ public class TestBuiltin_acosh extends TestBase { @Test public void testacosh6() { - assertEval(Ignored.OutputFormatting, "argv <- list(c(0.34345+233i,-0.34345+0.3334i));acosh(argv[[1]]);"); + assertEval("argv <- list(c(0.34345+233i,-0.34345+0.3334i));acosh(argv[[1]]);"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_agrep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_agrep.java index cd88e5033208122081f1069c6cd4a1e174b30d3a..2a993c5e008e5702571fa45eb184ee0f6e745979 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_agrep.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_agrep.java @@ -39,4 +39,16 @@ public class TestBuiltin_agrep extends TestBase { assertEval(Ignored.Unknown, "argv <- list('laysy', c('1 lazy', '1', '1 LAZY'), TRUE, FALSE, c(1L, 1L, 1L), c(2, NA, NA, NA, NA), FALSE, TRUE); .Internal(agrep(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]]))"); } + + @Test + public void testAgrep() { + assertEval("{ .Internal(agrep(7, \"42\", F, F, NULL, NULL, F, F)) }"); + assertEval("{ .Internal(agrep(character(), \"42\", F, F, NULL, NULL, F, F)) }"); + assertEval("{ .Internal(agrep(\"7\", 42, F, F, NULL, NULL, F, F)) }"); + + assertEval("{ .Internal(agrepl(7, \"42\", F, F, NULL, NULL, F, F)) }"); + assertEval("{ .Internal(agrepl(character(), \"42\", F, F, NULL, NULL, F, F)) }"); + assertEval("{ .Internal(agrepl(\"7\", 42, F, F, NULL, NULL, F, F)) }"); + } + } 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 3dd4c3fbe04b6fb936bace35c38c45a5efd467a0..b656b2072f9acb4bfba25aed04995ae8509a8034 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 @@ -29,13 +29,12 @@ public class TestBuiltin_all extends TestBase { @Test public void testall3() { - assertEval(Ignored.Unknown, "argv <- list(c(1, 1, 3, 1, 1, 3, 3, 3, 3), FALSE, NULL);all(argv[[1]],argv[[2]],argv[[3]]);"); + assertEval(Output.IgnoreWarningContext, "argv <- list(c(1, 1, 3, 1, 1, 3, 3, 3, 3), FALSE, NULL);all(argv[[1]],argv[[2]],argv[[3]]);"); } @Test public void testall4() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0, 0, 3, 0, 0, 0, 1, 0, 0, 2, 2, 3.2, -1, 1, 3.2, 4, 3, 0, 0, 0, 0, 3.2, 0, 0, 3.2, 0, 202, 0, 0, 0, 241, 0, 243, 0, 0), .Dim = c(5L, 7L), .Dimnames = list(c('r1', 'r2', 'r3', 'r4', 'r5'), c('c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7'))));all(argv[[1]]);"); + assertEval("argv <- list(structure(c(0, 0, 3, 0, 0, 0, 1, 0, 0, 2, 2, 3.2, -1, 1, 3.2, 4, 3, 0, 0, 0, 0, 3.2, 0, 0, 3.2, 0, 202, 0, 0, 0, 241, 0, 243, 0, 0), .Dim = c(5L, 7L), .Dimnames = list(c('r1', 'r2', 'r3', 'r4', 'r5'), c('c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7'))));all(argv[[1]]);"); } @Test @@ -119,10 +118,10 @@ public class TestBuiltin_all extends TestBase { assertEval("{ all(TRUE, TRUE, NA, na.rm=TRUE) }"); // FIXME coercion warning missing - assertEval(Ignored.Unknown, "{ all(1) }"); - assertEval(Ignored.Unknown, "{ all(0) }"); - assertEval(Ignored.Unknown, "{ all(TRUE,c(TRUE,TRUE),1) }"); - assertEval(Ignored.Unknown, "{ all(TRUE,c(TRUE,TRUE),1,0) }"); + assertEval("{ all(1) }"); + assertEval("{ all(0) }"); + assertEval(Output.IgnoreWarningContext, "{ all(TRUE,c(TRUE,TRUE),1) }"); + assertEval("{ all(TRUE,c(TRUE,TRUE),1,0) }"); assertEval("{ all(NULL) }"); assertEval("{ all(NULL, 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 a0f38363966745b5c8cb15e586280f948a5b79cc..54e5ed2846c7ff90c54ebdfbedcf09d4ff29e692 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 @@ -63,6 +63,6 @@ public class TestBuiltin_allnames extends TestBase { assertEval("{ all.names(expression(sin(x+y+x)), unique=F) }"); 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(expression(sin(x+y+x)), unique=NA) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_any.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_any.java index 55e38d938b0c8b1a72b993435d18d22e12feba09..2a2fc85c6ceaddd68bbe8e9bb995944873c60417 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_any.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_any.java @@ -39,7 +39,7 @@ public class TestBuiltin_any extends TestBase { @Test public void testany5() { - assertEval(Ignored.Unknown, "argv <- list(structure(c(14, 2, 0, 2, -7, 0), .Dim = c(3L, 2L)));any(argv[[1]]);"); + assertEval("argv <- list(structure(c(14, 2, 0, 2, -7, 0), .Dim = c(3L, 2L)));any(argv[[1]]);"); } @Test @@ -94,7 +94,7 @@ public class TestBuiltin_any extends TestBase { @Test public void testany17() { - assertEval(Ignored.Unknown, "argv <- list('NA');do.call('any', argv)"); + assertEval(Output.IgnoreWarningContext, "argv <- list('NA');do.call('any', argv)"); } @Test @@ -118,10 +118,8 @@ public class TestBuiltin_any extends TestBase { assertEval("{ any(NULL); }"); - // FIXME coercion warning missing - assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ any(1) }"); - // FIXME coercion warning missing - assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ any(0) }"); + assertEval("{ any(1) }"); + assertEval("{ any(0) }"); assertEval("{ d<-data.frame(c(1L,2L), c(10L, 20L)); any(d) }"); } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyNA.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyNA.java index 517851cc383fcab35fd0857ef817c1c24e50c9bf..cea95545ce24d229ee5943fa53220345c2d9141b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyNA.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyNA.java @@ -22,4 +22,13 @@ public class TestBuiltin_anyNA extends TestBase { public void testanyNA1() { assertEval("argv <- list(c(1.81566026854212e-304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));do.call('anyNA', argv)"); } + + @Test + public void testanyNA2() { + assertEval("anyNA(list(list(c(NA)),c(1)), recursive=TRUE)"); + assertEval("anyNA(list(list(c(NA)),c(1)), recursive=FALSE)"); + assertEval("anyNA(list(list(c(NA)),c(1)), recursive=c(FALSE,TRUE))"); + assertEval("anyNA(list(list(4,5,NA), 3), recursive=TRUE)"); + } + } 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 f5ab81834777d027daca6e32bc540ce92ab38283..a0c32a8668bb5f0fafa6ddc11f34714662ecad51 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 @@ -102,8 +102,7 @@ public class TestBuiltin_aperm extends TestBase { @Test public void testaperm16() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0.537261763078809+0i, 0.305061935059249+0.040985454461732i, 0.320062315956695-0.375563080684187i, 0.339383913939873+0.23302799386284i, -0.286918674221019+0.348301421162371i, 0.333809303929022+0i, -0.026432475532662-0.117484096686937i, 0.337897321317337+0.476009430788475i, -0.104431629205049-0.683873316213355i, -0.076600108155357+0.221030150757328i, 0.0283375771475593+0i, -0.439625821284244+0.725562264268455i, -0.093252555843956-0.328135936730845i, 0.099659684890077-0.362886081139892i, -0.146024566266657+0.013219412797458i, 0.437826208287688+0i, -0.047393587739568+0.297523229473226i, 0.053640336864496+0.244704251340016i, 0.189395328272566+0.197948900656662i, 0.744900728861518-0.157648587806964i, -0.63829956885596+0i, 0.190923866036828+0.209348060979014i, 0.478761262752136+0.086103851005322i, 0.365383456834977-0.041833555661111i, 0.222902888615007+0.301211043305794i), .Dim = c(5L, 5L)), 1:2, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))"); + assertEval("argv <- list(structure(c(0.537261763078809+0i, 0.305061935059249+0.040985454461732i, 0.320062315956695-0.375563080684187i, 0.339383913939873+0.23302799386284i, -0.286918674221019+0.348301421162371i, 0.333809303929022+0i, -0.026432475532662-0.117484096686937i, 0.337897321317337+0.476009430788475i, -0.104431629205049-0.683873316213355i, -0.076600108155357+0.221030150757328i, 0.0283375771475593+0i, -0.439625821284244+0.725562264268455i, -0.093252555843956-0.328135936730845i, 0.099659684890077-0.362886081139892i, -0.146024566266657+0.013219412797458i, 0.437826208287688+0i, -0.047393587739568+0.297523229473226i, 0.053640336864496+0.244704251340016i, 0.189395328272566+0.197948900656662i, 0.744900728861518-0.157648587806964i, -0.63829956885596+0i, 0.190923866036828+0.209348060979014i, 0.478761262752136+0.086103851005322i, 0.365383456834977-0.041833555661111i, 0.222902888615007+0.301211043305794i), .Dim = c(5L, 5L)), 1:2, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))"); } @Test @@ -197,19 +196,19 @@ public class TestBuiltin_aperm extends TestBase { 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]; }"); // perm is not a permutation vector - assertEval(Output.IgnoreErrorContext, "{ aperm(array(1,c( 3,3,3)), c(1,2,1)); }"); + assertEval("{ aperm(array(1,c( 3,3,3)), c(1,2,1)); }"); // perm value out of bounds - assertEval(Output.IgnoreErrorContext, "{ aperm(array(1,c(3,3,3)), c(1,2,0)); }"); + assertEval("{ aperm(array(1,c(3,3,3)), c(1,2,0)); }"); // first argument not an array - assertEval(Output.IgnoreErrorContext, "{ aperm(c(1,2,3)); }"); + assertEval("{ aperm(c(1,2,3)); }"); // Invalid first argument, not array - assertEval(Output.IgnoreErrorContext, "{ aperm(c(c(2,3), c(4,5), c(6,7)), c(3,4)) }"); + assertEval("{ aperm(c(c(2,3), c(4,5), c(6,7)), c(3,4)) }"); // invalid perm length - assertEval(Output.IgnoreErrorContext, "{ aperm(array(1,c(3,3,3)), c(1,2)); }"); + assertEval("{ aperm(array(1,c(3,3,3)), c(1,2)); }"); // Complex Vector assertEval("{ aperm(array(c(3+2i, 5+0i, 1+3i, 5-3i), c(2,2,2))) }"); 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 7afc488e9daa4c76a19ed3b9c2f78091522d3791..e4b02876266fcef15db7e46e230b691b4d3838db 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 @@ -116,8 +116,7 @@ public class TestBuiltin_array extends TestBase { @Test public void testarray20() { - assertEval(Ignored.Unknown, - "argv <- list(c(0.92317305817397+0i, 0.160449395256071+0.220125597679977i, 0.40353715410585+2.39063261466203i, -3.64092275386503+3.51619480964107i, -0.30877433127864+1.37503901638266i, -0.5590368753986+2.95994484328048i, 2.07117052177259-1.58552086053907i, 5.12796916272868+5.50114308371867i, 0.71791019962021-4.36295436036464i, 3.6182846955548+0.01693946731429i, 5.86560669896785+3.41674024963709i, 7.14153164455803+0i, 5.86560669896785-3.41674024963709i, 3.6182846955548-0.01693946731429i, 0.71791019962021+4.36295436036464i, 5.12796916272868-5.50114308371867i, 2.07117052177259+1.58552086053907i, -0.5590368753986-2.95994484328048i, -0.30877433127864-1.37503901638266i, -3.64092275386503-3.51619480964107i, 0.40353715410585-2.39063261466203i, 0.160449395256071-0.220125597679976i, 0.994686860835215+0i, -0.711636086238366+0.034977366507257i, -3.47255638259391-3.00654729467177i, -1.61617641806619-2.52564108817258i, -1.83729841635945+1.24025696654912i, -0.05940773912914+1.99807537840182i, 2.14861624215501+1.14547234755584i, -0.18935885218927+5.11711397439959i, 3.55025883223277-3.01463113510177i, 0.37587194655463-4.62160286369829i, -0.57999032040714+3.57394816552023i, -3.22078701201057+0i, -0.57999032040714-3.57394816552023i, 0.37587194655463+4.62160286369829i, 3.55025883223277+3.01463113510177i, -0.18935885218927-5.11711397439959i, 2.14861624215501-1.14547234755584i, -0.05940773912914-1.99807537840182i, -1.83729841635945-1.24025696654912i, -1.61617641806619+2.52564108817258i, -3.47255638259391+3.00654729467177i, -0.711636086238366-0.034977366507256i, -0.376031201145236+0i, 0.36561036190112-2.94822783523588i, 2.53378536984825+1.14599403212998i, -0.59345500414631-1.46249091231517i, -5.47371957596241-2.40983118775265i, 0.994698295196402+0.827012883372647i, 4.88614691865207-0.66440097322583i, -1.22869446246947-1.85036568311679i, 4.54719422944744-1.7507307644741i, -1.25805718969215-0.46461775748286i, -6.6950163960079-1.32606545879492i, -1.8510470181104-0i, -6.6950163960079+1.32606545879492i, -1.25805718969215+0.46461775748286i, 4.54719422944744+1.7507307644741i, -1.22869446246947+1.85036568311679i, 4.88614691865207+0.66440097322583i, 0.994698295196402-0.827012883372647i, -5.47371957596241+2.40983118775265i, -0.59345500414631+1.46249091231517i, 2.53378536984825-1.14599403212998i, 0.36561036190112+2.94822783523588i, 1.86949363581639+0i, 3.2510927680528+3.7297126359622i, 5.77117909703734-0.58113122596059i, -2.73489323319193-2.03739778844743i, 1.59256247378073-3.23882870600546i, -2.21652163259476+3.70287191787544i, -6.80966667821261-4.74346958471693i, -0.48551953206469-3.42445496113818i, -4.95350216815663-1.60107509096991i, -0.651322462114205+0.588393022429161i, 3.32067078328635+3.75999833207777i, -1.35013798358527+0i, 3.32067078328635-3.75999833207777i, -0.651322462114205-0.588393022429161i, -4.95350216815663+1.60107509096991i, -0.48551953206469+3.42445496113818i, -6.80966667821261+4.74346958471693i, -2.21652163259476-3.70287191787544i, 1.59256247378073+3.23882870600546i, -2.73489323319193+2.03739778844743i, 5.77117909703734+0.58113122596059i, 3.2510927680528-3.7297126359622i, -3.90806827793786+0i, -4.10078155861753-4.25996878161911i, -0.63461032994351-2.08074582601136i, -0.10593736514835-3.82022652091785i, 6.14817602783479+2.33657685886581i, 0.64431546852762-1.776774088028i, 3.43771282488202-3.00904523977379i, -3.6812061457129+3.53944567666635i, 3.07722382691467+4.5373840425762i, 3.3679046040028+7.20820407858926i, 7.47003475089893-0.4463480891006i, 13.9322715624418-0i, 7.47003475089893+0.4463480891006i, 3.3679046040028-7.20820407858926i, 3.07722382691467-4.5373840425762i, -3.6812061457129-3.53944567666635i, 3.43771282488202+3.00904523977379i, 0.64431546852762+1.776774088028i, 6.14817602783479-2.33657685886581i, -0.10593736514835+3.82022652091785i, -0.63461032994351+2.08074582601136i, -4.10078155861753+4.25996878161911i), c(22, 5), NULL); .Internal(array(argv[[1]], argv[[2]], argv[[3]]))"); + assertEval("argv <- list(c(0.92317305817397+0i, 0.160449395256071+0.220125597679977i, 0.40353715410585+2.39063261466203i, -3.64092275386503+3.51619480964107i, -0.30877433127864+1.37503901638266i, -0.5590368753986+2.95994484328048i, 2.07117052177259-1.58552086053907i, 5.12796916272868+5.50114308371867i, 0.71791019962021-4.36295436036464i, 3.6182846955548+0.01693946731429i, 5.86560669896785+3.41674024963709i, 7.14153164455803+0i, 5.86560669896785-3.41674024963709i, 3.6182846955548-0.01693946731429i, 0.71791019962021+4.36295436036464i, 5.12796916272868-5.50114308371867i, 2.07117052177259+1.58552086053907i, -0.5590368753986-2.95994484328048i, -0.30877433127864-1.37503901638266i, -3.64092275386503-3.51619480964107i, 0.40353715410585-2.39063261466203i, 0.160449395256071-0.220125597679976i, 0.994686860835215+0i, -0.711636086238366+0.034977366507257i, -3.47255638259391-3.00654729467177i, -1.61617641806619-2.52564108817258i, -1.83729841635945+1.24025696654912i, -0.05940773912914+1.99807537840182i, 2.14861624215501+1.14547234755584i, -0.18935885218927+5.11711397439959i, 3.55025883223277-3.01463113510177i, 0.37587194655463-4.62160286369829i, -0.57999032040714+3.57394816552023i, -3.22078701201057+0i, -0.57999032040714-3.57394816552023i, 0.37587194655463+4.62160286369829i, 3.55025883223277+3.01463113510177i, -0.18935885218927-5.11711397439959i, 2.14861624215501-1.14547234755584i, -0.05940773912914-1.99807537840182i, -1.83729841635945-1.24025696654912i, -1.61617641806619+2.52564108817258i, -3.47255638259391+3.00654729467177i, -0.711636086238366-0.034977366507256i, -0.376031201145236+0i, 0.36561036190112-2.94822783523588i, 2.53378536984825+1.14599403212998i, -0.59345500414631-1.46249091231517i, -5.47371957596241-2.40983118775265i, 0.994698295196402+0.827012883372647i, 4.88614691865207-0.66440097322583i, -1.22869446246947-1.85036568311679i, 4.54719422944744-1.7507307644741i, -1.25805718969215-0.46461775748286i, -6.6950163960079-1.32606545879492i, -1.8510470181104-0i, -6.6950163960079+1.32606545879492i, -1.25805718969215+0.46461775748286i, 4.54719422944744+1.7507307644741i, -1.22869446246947+1.85036568311679i, 4.88614691865207+0.66440097322583i, 0.994698295196402-0.827012883372647i, -5.47371957596241+2.40983118775265i, -0.59345500414631+1.46249091231517i, 2.53378536984825-1.14599403212998i, 0.36561036190112+2.94822783523588i, 1.86949363581639+0i, 3.2510927680528+3.7297126359622i, 5.77117909703734-0.58113122596059i, -2.73489323319193-2.03739778844743i, 1.59256247378073-3.23882870600546i, -2.21652163259476+3.70287191787544i, -6.80966667821261-4.74346958471693i, -0.48551953206469-3.42445496113818i, -4.95350216815663-1.60107509096991i, -0.651322462114205+0.588393022429161i, 3.32067078328635+3.75999833207777i, -1.35013798358527+0i, 3.32067078328635-3.75999833207777i, -0.651322462114205-0.588393022429161i, -4.95350216815663+1.60107509096991i, -0.48551953206469+3.42445496113818i, -6.80966667821261+4.74346958471693i, -2.21652163259476-3.70287191787544i, 1.59256247378073+3.23882870600546i, -2.73489323319193+2.03739778844743i, 5.77117909703734+0.58113122596059i, 3.2510927680528-3.7297126359622i, -3.90806827793786+0i, -4.10078155861753-4.25996878161911i, -0.63461032994351-2.08074582601136i, -0.10593736514835-3.82022652091785i, 6.14817602783479+2.33657685886581i, 0.64431546852762-1.776774088028i, 3.43771282488202-3.00904523977379i, -3.6812061457129+3.53944567666635i, 3.07722382691467+4.5373840425762i, 3.3679046040028+7.20820407858926i, 7.47003475089893-0.4463480891006i, 13.9322715624418-0i, 7.47003475089893+0.4463480891006i, 3.3679046040028-7.20820407858926i, 3.07722382691467-4.5373840425762i, -3.6812061457129-3.53944567666635i, 3.43771282488202+3.00904523977379i, 0.64431546852762+1.776774088028i, 6.14817602783479-2.33657685886581i, -0.10593736514835+3.82022652091785i, -0.63461032994351+2.08074582601136i, -4.10078155861753+4.25996878161911i), c(22, 5), NULL); .Internal(array(argv[[1]], argv[[2]], argv[[3]]))"); } @Test @@ -154,4 +153,20 @@ public class TestBuiltin_array extends TestBase { public void testarray27() { assertEval("argv <- list(-1, c(3L, 2L), list(c('a', 'b', 'c'), NULL)); .Internal(array(argv[[1]], argv[[2]], argv[[3]]))"); } + + @Test + public void testArray() { + assertEval(Output.IgnoreWarningContext, "{ array(1:4, 1:2, 4) }"); + assertEval(Output.IgnoreWarningContext, "{ array(1:4, c(1+2i, 2+2i)) }"); + assertEval("{ array(as.raw(1:4)) }"); + assertEval("{ array(1:4, integer()) }"); + assertEval("{ array(NULL) }"); + assertEval("{ array(NA) }"); + assertEval("{ array(1:4, NULL) }"); + assertEval("{ .Internal(array(1:4, NULL, NULL)) }"); + assertEval("{ .Internal(array(NULL, 1, NULL)) }"); + assertEval("{ .Internal(array(NA, 1, NULL)) }"); + assertEval("{ f<-function() 42; .Internal(array(f, 1, NULL)) }"); + } + } 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 bdd5b4596b80bf4a7e1a0946cb8cc34723925f20..e8c02db81367dfeafb82b671b8e4771134568f50 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 @@ -34,8 +34,7 @@ public class TestBuiltin_ascomplex extends TestBase { @Test public void testascomplex4() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(-0.626453810742332, 0.183643324222082, -0.835628612410047, 1.59528080213779, 0.329507771815361, -0.820468384118015, 0.487429052428485, 0.738324705129217, 0.575781351653492, -0.305388387156356, 1.51178116845085, 0.389843236411431, -0.621240580541804, -2.2146998871775, 1.12493091814311, -0.0449336090152309, -0.0161902630989461, 0.943836210685299, 0.821221195098089, 0.593901321217509, 0.918977371608218, 0.782136300731067, 0.0745649833651906, -1.98935169586337, 0.61982574789471), .Dim = c(5L, 5L), .Dimnames = list(c('1', '2', '3', '4', '5'), c('a', 'b', 'c', 'd', 'e'))));as.complex(argv[[1]]);"); + assertEval("argv <- list(structure(c(-0.626453810742332, 0.183643324222082, -0.835628612410047, 1.59528080213779, 0.329507771815361, -0.820468384118015, 0.487429052428485, 0.738324705129217, 0.575781351653492, -0.305388387156356, 1.51178116845085, 0.389843236411431, -0.621240580541804, -2.2146998871775, 1.12493091814311, -0.0449336090152309, -0.0161902630989461, 0.943836210685299, 0.821221195098089, 0.593901321217509, 0.918977371608218, 0.782136300731067, 0.0745649833651906, -1.98935169586337, 0.61982574789471), .Dim = c(5L, 5L), .Dimnames = list(c('1', '2', '3', '4', '5'), c('a', 'b', 'c', 'd', 'e'))));as.complex(argv[[1]]);"); } @Test @@ -45,8 +44,7 @@ public class TestBuiltin_ascomplex extends TestBase { @Test public void testascomplex6() { - assertEval(Ignored.Unknown, - "argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = 'data.frame'), structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = 'data.frame'));as.complex(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = 'data.frame'), structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = 'data.frame'));as.complex(argv[[1]],argv[[2]]);"); } @Test @@ -66,7 +64,7 @@ public class TestBuiltin_ascomplex extends TestBase { @Test public void testascomplex10() { - assertEval(Ignored.Unknown, "argv <- list(structure(list(a = 1), .Names = 'a'));as.complex(argv[[1]]);"); + assertEval("argv <- list(structure(list(a = 1), .Names = 'a'));as.complex(argv[[1]]);"); } @Test @@ -92,9 +90,13 @@ public class TestBuiltin_ascomplex extends TestBase { assertEval("{ as.complex(\"0x42\") }"); assertEval("{ as.complex(NULL) }"); - assertEval(Ignored.Unknown, "{ as.complex(\"1e10+5i\") }"); - assertEval(Ignored.Unknown, "{ as.complex(\"-.1e10+5i\") }"); + assertEval("{ as.complex(\"1e10+5i\") }"); + assertEval("{ as.complex(\"-.1e10+5i\") }"); assertEval(Ignored.Unknown, "{ as.complex(\"1e-2+3i\") }"); assertEval(Ignored.Unknown, "{ as.complex(\"+.1e+2-3i\") }"); + + assertEval("{ as.complex(list(42)) }"); + assertEval(Output.IgnoreErrorContext, "{ as.complex(list(NULL)) }"); + assertEval(Output.IgnoreWarningContext, "{ as.complex(list(\"foo\")) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asexpression.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asexpression.java index cfa9f221b2bd666442033844a0d29f175176c495..f872324356b50d5c0ec045acd50a2dfa7cada4bf 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asexpression.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asexpression.java @@ -33,6 +33,6 @@ public class TestBuiltin_asexpression extends TestBase { assertEval("{ as.expression(list(1,2)) }"); assertEval("{ as.expression(list(\"x\" = 1, \"y\" = 2)) }"); assertEval(Output.IgnoreErrorContext, "{ as.expression(sum) }"); - assertEval("{ as.expression(function()) }"); + assertEval(Output.IgnoreErrorContext, "{ as.expression(function() {}) }"); } } 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 fd5ab3b839035c4da732444ea11a2285d5ed31f5..b0432a40b7d1b1a86be53c5f91686a31760b0bb6 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,5 +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(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_asmatrix.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asmatrix.java index 63288a811b7d9b331691e5f1ad4c31e7c7696f28..549f56d5816490f9e8f91868a3c3a270eb920004 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 @@ -71,7 +71,8 @@ public class TestBuiltin_asmatrix extends TestBase { assertEval("{ matrix(1:6, ncol=3:5,byrow=TRUE)}"); assertEval("{ matrix(TRUE,FALSE,FALSE,TRUE)}"); - assertEval("{ matrix(c(NaN,4+5i,2+0i,5+10i)} "); + // prints as NA not NaN + assertEval(Ignored.Unknown, "{ matrix(c(NaN,4+5i,2+0i,5+10i)) } "); // FIXME missing warning assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ matrix(c(1,2,3,4),3,2) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_assign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_assign.java index 5f58a4207b4a06023d731072559ddc46e703c28b..56b2634e7bd148379b854990670f847e107d8261 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_assign.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_assign.java @@ -22,4 +22,10 @@ public class TestBuiltin_assign extends TestBase { public void testassign1() { assertEval("argv <- structure(list(x = '`', value = TRUE), .Names = c('x', 'value'));do.call('assign', argv)"); } + + @Test + public void testassign() { + assertEval("x <- c(1,2,4); e <- new.env(); assign('foo', x, e); x[[1]] <- 5; x; get('foo', e)"); + assertEval("x <- c(1,2,4); e <- new.env(); assign('foo', x, e, inherits=0); x[[1]] <- 5; x; get('foo', e)"); + } } 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 32836f39c093ee713aa4422d08768ec33416a3a5..44c012746a1460dd4c1cc3737edaf1f5260f8534 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 @@ -144,7 +144,7 @@ public class TestBuiltin_asvector extends TestBase { @Test public void testasvector26() { - assertEval(Ignored.Unknown, "argv <- list(quote(list(V1 = c('a', 'd e', 'h'), V2 = c('b'', 'f', 'i'), V3 = c('c', 'g', 'j\\nk l m'))), 'list'); .Internal(as.vector(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(quote(list(V1 = c('a', 'd e', 'h'), V2 = c('b\\'', 'f', 'i'), V3 = c('c', 'g', 'j\\nk l m'))), 'list'); .Internal(as.vector(argv[[1]], argv[[2]]))"); } @Test @@ -164,7 +164,7 @@ public class TestBuiltin_asvector extends TestBase { @Test public void testasvector30() { - assertEval(Ignored.Unknown, "argv <- list(list('a', 'b', 'c'), 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(list('a', 'b', 'c'), 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))"); } @Test @@ -417,13 +417,15 @@ public class TestBuiltin_asvector extends TestBase { assertEval("{ as.vector(NULL, \"list\") }"); assertEval("{ as.vector(NULL) }"); + assertEval("as.vector(as.symbol('asdf'), 'symbol')"); + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); as.vector(x) }"); assertEval("as.vector(x~z)"); assertEval(Ignored.Unimplemented, "as.vector(file(''))"); assertEval(Output.IgnoreErrorContext, "{ as.vector(42, NULL) }"); - assertEval("{ as.vector(42, c(\"character\", \"character\") }"); + assertEval(Output.IgnoreErrorContext, "{ as.vector(42, c(\"character\", \"character\")) }"); assertEval(Output.IgnoreErrorContext, "{ as.vector(42, character()) }"); } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan.java index c339e072af39757ea623d215a78d2fe1250fc162..607243f543229a5c44edb5ca55214e1e31b52bcc 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan.java @@ -29,7 +29,7 @@ public class TestBuiltin_atan extends TestBase { @Test public void testatan3() { - assertEval(Ignored.OutputFormatting, "argv <- list(c(0+2i, 0.0001+2i, 0-2i, 0-2.0001i));atan(argv[[1]]);"); + assertEval("argv <- list(c(0+2i, 0.0001+2i, 0-2i, 0-2.0001i));atan(argv[[1]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atanh.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atanh.java index d1953665b0019499f7c21c104978770a40670d26..2ae66c2a5175e07e7ecd1626660e6fa7d751f264 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atanh.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atanh.java @@ -34,6 +34,6 @@ public class TestBuiltin_atanh extends TestBase { @Test public void testatanh4() { - assertEval(Ignored.OutputFormatting, "argv <- list(c(2+0i, 2-0.0001i, -2+0i, -2+0.0001i));atanh(argv[[1]]);"); + assertEval("argv <- list(c(2+0i, 2-0.0001i, -2+0i, -2+0.0001i));atanh(argv[[1]]);"); } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..9162f204511713221e774dd47c8c21b17d771eac --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attach.java @@ -0,0 +1,56 @@ +/* + * 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.test.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestBuiltin_attach extends TestBase { + @Test + public void basicTests() { + assertEval("d <- data.frame(colNameX=c(1,2,3)); attach(d); colNameX"); + assertEval("d <- list(colNameX=c(1,2,3)); attach(d); colNameX"); + assertEval("e <- attach(NULL); attr(e, 'name')"); + assertEval("d <- list(col=c(1,2,3)); e <- attach(d, name='hello'); attr(e, 'name')"); + } + + @Test + public void testArguments() { + assertEval("attach('string')"); + assertEval(Output.IgnoreErrorMessage, "attach(list(x=42), pos='string')"); + assertEval(Output.IgnoreErrorContext, "attach(list(), name=42)"); + assertEval("detach('string')"); + } + + @Test + public void detach() { + assertEval("d <- list(colNameX=c(1,2,3)); attach(d); detach(d); colNameX"); + } + + @Test + public void sharingTests() { + assertEval("d <- data.frame(colNameX=c(1,2,3)); attach(d); d$colNameX[1] <- 42; colNameX"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attr.java index e5c6ae381872de568fd794b203b6372300344d7c..47cd7772639c768c751213aef48511a7198a6dfa 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attr.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attr.java @@ -237,4 +237,10 @@ public class TestBuiltin_attr extends TestBase { public void testattr45() { assertEval("argv <- list(c(35.2589338684655, 59.5005803666983, 12.4529321610302, 2.53579570262684, 10.370198579714, 42.0067149618146, 8.14319638132861, 34.0508943233725, 7.78517191057496, 26.9998965458032, 6.70435391953205, 3.62502215105156, 2.59277105754344, 14.4998960151485, 6.70435391953205, 5.8000097831969, 32.741875696675, 59.5015090627504, 13.5512565366133, 4.46460764999704, 9.62989278443572, 42.0073706103832, 8.86141045052292, 59.9511558158597, 7.22940551532861, 27.0003179651772, 7.29566488446303, 6.38233656214029, 2.40767880256155, 14.5001223322046, 7.29566488446303, 10.2116933242272), 'dim');attr(argv[[1]],argv[[2]]);"); } + + @Test + public void testExactMatch() { + assertEval("x <- c(1, 3); attr(x, 'abc') <- 42; attr(x, 'ab', exact=TRUE)"); + assertEval(Ignored.Unimplemented, "x <- c(1,2); attr(x, 'row.namess') <- 42; attr(x, 'row.names')"); + } } 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 aa4d37ba5916c2873b0342df09f4f47be92b3386..b8b553bad99c00077d46ab1bd2902978b4fab2f2 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 @@ -97,4 +97,10 @@ public class TestBuiltin_attrassign extends TestBase { public void testattrassign16() { assertEval("argv <- list(structure(c(0, -187, -34, 0, 165, 0, -95, 121, 107, 0, 41, 0, 0, 93, 0), .Dim = c(5L, 3L)), 'dimnames', value = NULL);`attr<-`(argv[[1]],argv[[2]],argv[[3]]);"); } + + @Test + public void testArgsCasts() { + assertEval(Output.IgnoreErrorContext, "x<-42; attr(x, NULL) <- NULL"); + assertEval(Output.IgnoreErrorContext, "x<-42; attr(x, 42) <- NULL"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributesassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributesassign.java index fecf05d31c434d17aa9e09d730b46f20ea801b65..e9fa6045044912f1acb5f1d95b0029f28b8c5993 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributesassign.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributesassign.java @@ -47,4 +47,10 @@ public class TestBuiltin_attributesassign extends TestBase { public void testattributesassign6() { assertEval("argv <- list(structure(c(1, 1, 1, 1, 2, 3), .Dim = c(3L, 2L), .Dimnames = list(NULL, c('I', 'a')), foo = 'bar', class = 'matrix'), value = structure(list(class = 'matrix', foo = 'bar', dimnames = list(NULL, c('I', 'a')), dim = c(3L, 2L)), .Names = c('class', 'foo', 'dimnames', 'dim')));`attributes<-`(argv[[1]],argv[[2]]);"); } + + @Test + public void testArgsCasts() { + assertEval("x <- 42; attributes(x) <- 44"); + assertEval("x <- 42; attributes(x) <- NULL"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseAnd.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseAnd.java index bc5109260fa03710cab03d40e1335d0c18de281e..5e17f59f744d6ad621bc4bbf2e5f61a07f0c0144 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseAnd.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseAnd.java @@ -34,9 +34,9 @@ public class TestBuiltin_bitwiseAnd extends TestBase { assertEval("{ bitwAnd(c(10L,20L,30L,40L), c(3,5,7)) }"); assertEval("{ bitwAnd(c(10.5,11.6,17.8), c(5L,7L,8L)) }"); - assertEval(Ignored.Unknown, "{ bitwAnd(NULL, NULL) }"); - assertEval(Ignored.Unknown, "{ bitwAnd(c(), c(1,2,3)) }"); + assertEval(Output.IgnoreErrorContext, "{ bitwAnd(NULL, NULL) }"); + assertEval(Output.IgnoreErrorContext, Output.IgnoreErrorMessage, "{ bitwAnd(c(), c(1,2,3)) }"); // Error message mismatch - assertEval(Output.IgnoreErrorContext, "{ bitwAnd(c(1,2,3,4), c(TRUE)) }"); + assertEval(Output.IgnoreErrorMessage, "{ bitwAnd(c(1,2,3,4), c(TRUE)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseOr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseOr.java index 607ca2ddba0cfa2f8a07f822b720f233a4674df7..830c2e07353f7a0b52f592d1d3a57c8b1975d432 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseOr.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseOr.java @@ -27,6 +27,6 @@ public class TestBuiltin_bitwiseOr extends TestBase { assertEval("{ bitwOr(c(10,11,12,13,14,15), c(1,1,1,1,1,1)) }"); assertEval("{ bitwOr(c(25,57,66), c(10,20,30,40,50,60)) }"); // Error message mismatch - assertEval(Output.IgnoreErrorContext, "{ bitwOr(c(1,2,3,4), c(3+3i)) }"); + assertEval(Output.IgnoreErrorMessage, "{ bitwOr(c(1,2,3,4), c(3+3i)) }"); } } 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 6cd42ccb8aabc97d2f0b9ae370c60b97a9d3ba6c..6e33441b3be4ea000c0c32de930a6a988bd4e62e 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 @@ -27,14 +27,15 @@ public class TestBuiltin_bitwiseShiftL extends TestBase { 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)) }"); + assertEval("{ bitwShiftL(c(8,4,2), NULL) }"); - assertEval(Output.IgnoreErrorContext, "{ bitwShiftL(TRUE, c(TRUE, FALSE)) }"); + assertEval("{ bitwShiftL(TRUE, c(TRUE, FALSE)) }"); // Error message mismatch - assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ bitwShiftL(c(3+3i), c(3,2,4)) }"); + assertEval(Output.IgnoreErrorContext, "{ bitwShiftL(c(3+3i), c(3,2,4)) }"); // Warning message mismatch - assertEval(Ignored.Unknown, "{ bitwShiftL(c(3,2,4), c(3+3i)) }"); + assertEval(Output.IgnoreWarningContext, "{ bitwShiftL(c(3,2,4), c(3+3i)) }"); // No warning message printed for NAs produced by coercion - assertEval(Ignored.Unknown, "{ bitwShiftL(c(1,2,3,4), c(\"a\")) }"); + 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 dde3268bc5e00f4519827eca4d7d8cb5a9d410b0..459a1421dddec339bff3acb18f6736b9d8c23e56 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 @@ -28,7 +28,7 @@ public class TestBuiltin_bitwiseShiftR extends TestBase { assertEval("{ bitwShiftR(c(100,200,300), 1) }"); assertEval("{ bitwShiftR(c(25,57,66), c(10,20,30,40,50,60)) }"); - assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ bitwShiftR(c(3,2,4), c(3+3i)) }"); + assertEval(Output.IgnoreWarningContext, "{ 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_bitwiseXor.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseXor.java index 44507562922a2a7f8b92a1d66fedbfbec58975a4..6e242a3f7a2d49991105e91ff8e3a5429118aa83 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseXor.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseXor.java @@ -28,6 +28,6 @@ public class TestBuiltin_bitwiseXor extends TestBase { assertEval("{ bitwXor(c(25,57,66), c(10,20,30,40,50,60)) }"); assertEval("{ bitwXor(20,30) }"); - assertEval(Output.IgnoreErrorContext, "{ bitwXor(c(\"r\"), c(16,17)) }"); + assertEval(Output.IgnoreErrorMessage, "{ bitwXor(c(\"r\"), c(16,17)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_c.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_c.java index 675c028cf17f9094cfe57ba181536738ab49672a..9d89b224ec1b0c1f2e47e9578001036af6f6c4e9 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_c.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_c.java @@ -535,8 +535,8 @@ public class TestBuiltin_c extends TestBase { // which seems to invoke deparse, so we just check the c didn't fail. assertEval("{ f <- function() { }; length(c(f, 2)) == 2 }"); - assertEval("{ e1 <- new.env(), e2 <- new.env(); c(e1, e2) }"); - assertEval("{ e1 <- new.env(), c(e1, 3) }"); + assertEval(Output.ContainsReferences, "{ e1 <- new.env(); e2 <- new.env(); c(e1, e2) }"); + assertEval(Output.ContainsReferences, "{ e1 <- new.env(); c(e1, 3) }"); assertEval("{ setClass(\"foo\", representation(d=\"numeric\")); x<-new(\"foo\", d=42); y<-c(x, 7); y[[1]] }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_choose.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_choose.java index 6ae2f0a86f6e9023a64d151bbc47ad3202d08146..46caa96a84130aa0ec979f491cb671cd7bc1a1de 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_choose.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_choose.java @@ -30,11 +30,18 @@ public class TestBuiltin_choose extends TestBase { @Test public void testchooseWithLogical() { - assertEval(Ignored.Unimplemented, ".Internal(choose(logical(0), logical(0)))"); + assertEval(".Internal(choose(logical(0), logical(0)))"); } @Test public void testchoose4() { assertEval(".Internal(choose(0.5, 0:10))"); } + + @Test + public void testWithNonNumericArgs() { + // GnuR choose error message does not show args evaluated + assertEval(Output.IgnoreErrorContext, ".Internal(choose('hello', 3))"); + assertEval(Output.IgnoreErrorContext, ".Internal(choose(3, 'hello'))"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_col.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_col.java index e279cf63709bc115079deccc20229bc256f1a964..5f2cad29df2c8a3caf5c32fa8d54080af1870187 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_col.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_col.java @@ -32,11 +32,11 @@ public class TestBuiltin_col extends TestBase { assertEval("{ ma <- matrix(1:12, 3, 4) ; col(ma) }"); assertEval("{ ma <- cbind(x = 1:10, y = (-4:5)^2) ; col(ma) }"); - assertEval(Output.IgnoreErrorContext, "{ col(c(1,2,3)) }"); + assertEval("{ col(c(1,2,3)) }"); } @Test public void testCasts0() { - assertEval(Output.IgnoreErrorContext, "col(NULL)"); + assertEval("col(NULL)"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_colMeans.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_colMeans.java index f1fabfff8609d544e56df2f0920fa171452abedd..b35955c9cf4696abfab70ff619aae08fcb98bf37 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_colMeans.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_colMeans.java @@ -105,6 +105,9 @@ public class TestBuiltin_colMeans extends TestBase { assertEval("{colMeans(matrix(c(NA,NaN,NaN,NA),ncol=2,nrow=2))}"); assertEval("{ a = colSums(array(1:24,c(2,3,4))); colMeans(a)}"); - assertEval(Ignored.Unknown, "{colMeans(matrix(c(NaN,4+5i,2+0i,5+10i),nrow=2,ncol=2), na.rm = TRUE)}"); + // Following fails not because of colMeans implementation, but because following code does + // not work: + // x <- c(NaN, 3+2i); xre <- Re(x); xim <- (0+1i) * Im(x); xre + xim + assertEval(Ignored.ImplementationError, "{colMeans(matrix(c(NaN,4+5i,2+0i,5+10i),nrow=2,ncol=2), na.rm = TRUE)}"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_colSums.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_colSums.java index ebe0d3c1c9b8f24284961fa03de03264e3362ec9..9bd8089dc09d5ce4ebd46847a95652bdd6fa4f1a 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_colSums.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_colSums.java @@ -12,10 +12,6 @@ package com.oracle.truffle.r.test.builtins; import org.junit.Test; -import com.oracle.truffle.api.TruffleLanguage; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.RootNode; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.test.TestBase; // Checkstyle: stop line length check @@ -95,19 +91,4 @@ public class TestBuiltin_colSums extends TestBase { // colSums on array have correct values assertEval("{ a = colSums(array(1:24,c(2,3,4))); c(a[1,1],a[2,2],a[3,3],a[3,4]) }"); } - - class RBuiltinRootNode extends RootNode { - - @Child private RBuiltinNode builtinNode; - - RBuiltinRootNode(RBuiltinNode builtinNode) { - super(TruffleLanguage.class, null, null); - this.builtinNode = builtinNode; - } - - @Override - public Object execute(VirtualFrame frame) { - return builtinNode.execute(frame); - } - } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cosh.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cosh.java index c5f00c7d93c861ac68ebcda4bdf90b4f4c0dd558..96ada9429744986d315fb28c8f26d2d913f3bc63 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cosh.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cosh.java @@ -39,7 +39,6 @@ public class TestBuiltin_cosh extends TestBase { @Test public void testcosh5() { - assertEval(Ignored.OutputFormatting, - "argv <- list(c(0-3i, 0-2.96984924623116i, 0-2.93969849246231i, 0-2.90954773869347i, 0-2.87939698492462i, 0-2.84924623115578i, 0-2.81909547738693i, 0-2.78894472361809i, 0-2.75879396984925i, 0-2.7286432160804i, 0-2.69849246231156i, 0-2.66834170854271i, 0-2.63819095477387i, 0-2.60804020100502i, 0-2.57788944723618i, 0-2.54773869346734i, 0-2.51758793969849i, 0-2.48743718592965i, 0-2.4572864321608i, 0-2.42713567839196i, 0-2.39698492462312i, 0-2.36683417085427i, 0-2.33668341708543i, 0-2.30653266331658i, 0-2.27638190954774i, 0-2.24623115577889i, 0-2.21608040201005i, 0-2.18592964824121i, 0-2.15577889447236i, 0-2.12562814070352i, 0-2.09547738693467i, 0-2.06532663316583i, 0-2.03517587939699i, 0-2.00502512562814i, 0-1.9748743718593i, 0-1.94472361809045i, 0-1.91457286432161i, 0-1.88442211055276i, 0-1.85427135678392i, 0-1.82412060301508i, 0-1.79396984924623i, 0-1.76381909547739i, 0-1.73366834170854i, 0-1.7035175879397i, 0-1.67336683417085i, 0-1.64321608040201i, 0-1.61306532663317i, 0-1.58291457286432i, 0-1.55276381909548i, 0-1.52261306532663i, 0-1.49246231155779i, 0-1.46231155778894i, 0-1.4321608040201i, 0-1.40201005025126i, 0-1.37185929648241i, 0-1.34170854271357i, 0-1.31155778894472i, 0-1.28140703517588i, 0-1.25125628140704i, 0-1.22110552763819i, 0-1.19095477386935i, 0-1.1608040201005i, 0-1.13065326633166i, 0-1.10050251256281i, 0-1.07035175879397i, 0-1.04020100502513i, 0-1.01005025125628i, 0-0.979899497487437i, 0-0.949748743718593i, 0-0.919597989949749i, 0-0.889447236180905i, 0-0.859296482412061i, 0-0.829145728643216i, 0-0.798994974874372i, 0-0.768844221105528i, 0-0.738693467336684i, 0-0.70854271356784i, 0-0.678391959798995i, 0-0.648241206030151i, 0-0.618090452261307i, 0-0.587939698492463i, 0-0.557788944723618i, 0-0.527638190954774i, 0-0.49748743718593i, 0-0.467336683417086i, 0-0.437185929648241i, 0-0.407035175879397i, 0-0.376884422110553i, 0-0.346733668341709i, 0-0.316582914572864i, 0-0.28643216080402i, 0-0.256281407035176i, 0-0.226130653266332i, 0-0.195979899497488i, 0-0.165829145728643i, 0-0.135678391959799i, 0-0.105527638190955i, 0-0.0753768844221105i, 0-0.0452261306532664i, 0-0.0150753768844223i, 0+0.0150753768844218i, 0+0.0452261306532664i, 0+0.0753768844221105i, 0+0.105527638190955i, 0+0.135678391959799i, 0+0.165829145728643i, 0+0.195979899497488i, 0+0.226130653266332i, 0+0.256281407035176i, 0+0.28643216080402i, 0+0.316582914572864i, 0+0.346733668341709i, 0+0.376884422110553i, 0+0.407035175879397i, 0+0.437185929648241i, 0+0.467336683417085i, 0+0.49748743718593i, 0+0.527638190954774i, 0+0.557788944723618i, 0+0.587939698492462i, 0+0.618090452261306i, 0+0.648241206030151i, 0+0.678391959798995i, 0+0.708542713567839i, 0+0.738693467336683i, 0+0.768844221105527i, 0+0.798994974874372i, 0+0.829145728643216i, 0+0.85929648241206i, 0+0.889447236180904i, 0+0.919597989949748i, 0+0.949748743718593i, 0+0.979899497487437i, 0+1.01005025125628i, 0+1.04020100502513i, 0+1.07035175879397i, 0+1.10050251256281i, 0+1.13065326633166i, 0+1.1608040201005i, 0+1.19095477386935i, 0+1.22110552763819i, 0+1.25125628140704i, 0+1.28140703517588i, 0+1.31155778894472i, 0+1.34170854271357i, 0+1.37185929648241i, 0+1.40201005025126i, 0+1.4321608040201i, 0+1.46231155778894i, 0+1.49246231155779i, 0+1.52261306532663i, 0+1.55276381909548i, 0+1.58291457286432i, 0+1.61306532663317i, 0+1.64321608040201i, 0+1.67336683417085i, 0+1.7035175879397i, 0+1.73366834170854i, 0+1.76381909547739i, 0+1.79396984924623i, 0+1.82412060301507i, 0+1.85427135678392i, 0+1.88442211055276i, 0+1.91457286432161i, 0+1.94472361809045i, 0+1.9748743718593i, 0+2.00502512562814i, 0+2.03517587939698i, 0+2.06532663316583i, 0+2.09547738693467i, 0+2.12562814070352i, 0+2.15577889447236i, 0+2.18592964824121i, 0+2.21608040201005i, 0+2.24623115577889i, 0+2.27638190954774i, 0+2.30653266331658i, 0+2.33668341708543i, 0+2.36683417085427i, 0+2.39698492462312i, 0+2.42713567839196i, 0+2.4572864321608i, 0+2.48743718592965i, 0+2.51758793969849i, 0+2.54773869346734i, 0+2.57788944723618i, 0+2.60804020100502i, 0+2.63819095477387i, 0+2.66834170854271i, 0+2.69849246231156i, 0+2.7286432160804i, 0+2.75879396984925i, 0+2.78894472361809i, 0+2.81909547738693i, 0+2.84924623115578i, 0+2.87939698492462i, 0+2.90954773869347i, 0+2.93969849246231i, 0+2.96984924623116i, 0+3i));cosh(argv[[1]]);"); + assertEval("argv <- list(c(0-3i, 0-2.96984924623116i, 0-2.93969849246231i, 0-2.90954773869347i, 0-2.87939698492462i, 0-2.84924623115578i, 0-2.81909547738693i, 0-2.78894472361809i, 0-2.75879396984925i, 0-2.7286432160804i, 0-2.69849246231156i, 0-2.66834170854271i, 0-2.63819095477387i, 0-2.60804020100502i, 0-2.57788944723618i, 0-2.54773869346734i, 0-2.51758793969849i, 0-2.48743718592965i, 0-2.4572864321608i, 0-2.42713567839196i, 0-2.39698492462312i, 0-2.36683417085427i, 0-2.33668341708543i, 0-2.30653266331658i, 0-2.27638190954774i, 0-2.24623115577889i, 0-2.21608040201005i, 0-2.18592964824121i, 0-2.15577889447236i, 0-2.12562814070352i, 0-2.09547738693467i, 0-2.06532663316583i, 0-2.03517587939699i, 0-2.00502512562814i, 0-1.9748743718593i, 0-1.94472361809045i, 0-1.91457286432161i, 0-1.88442211055276i, 0-1.85427135678392i, 0-1.82412060301508i, 0-1.79396984924623i, 0-1.76381909547739i, 0-1.73366834170854i, 0-1.7035175879397i, 0-1.67336683417085i, 0-1.64321608040201i, 0-1.61306532663317i, 0-1.58291457286432i, 0-1.55276381909548i, 0-1.52261306532663i, 0-1.49246231155779i, 0-1.46231155778894i, 0-1.4321608040201i, 0-1.40201005025126i, 0-1.37185929648241i, 0-1.34170854271357i, 0-1.31155778894472i, 0-1.28140703517588i, 0-1.25125628140704i, 0-1.22110552763819i, 0-1.19095477386935i, 0-1.1608040201005i, 0-1.13065326633166i, 0-1.10050251256281i, 0-1.07035175879397i, 0-1.04020100502513i, 0-1.01005025125628i, 0-0.979899497487437i, 0-0.949748743718593i, 0-0.919597989949749i, 0-0.889447236180905i, 0-0.859296482412061i, 0-0.829145728643216i, 0-0.798994974874372i, 0-0.768844221105528i, 0-0.738693467336684i, 0-0.70854271356784i, 0-0.678391959798995i, 0-0.648241206030151i, 0-0.618090452261307i, 0-0.587939698492463i, 0-0.557788944723618i, 0-0.527638190954774i, 0-0.49748743718593i, 0-0.467336683417086i, 0-0.437185929648241i, 0-0.407035175879397i, 0-0.376884422110553i, 0-0.346733668341709i, 0-0.316582914572864i, 0-0.28643216080402i, 0-0.256281407035176i, 0-0.226130653266332i, 0-0.195979899497488i, 0-0.165829145728643i, 0-0.135678391959799i, 0-0.105527638190955i, 0-0.0753768844221105i, 0-0.0452261306532664i, 0-0.0150753768844223i, 0+0.0150753768844218i, 0+0.0452261306532664i, 0+0.0753768844221105i, 0+0.105527638190955i, 0+0.135678391959799i, 0+0.165829145728643i, 0+0.195979899497488i, 0+0.226130653266332i, 0+0.256281407035176i, 0+0.28643216080402i, 0+0.316582914572864i, 0+0.346733668341709i, 0+0.376884422110553i, 0+0.407035175879397i, 0+0.437185929648241i, 0+0.467336683417085i, 0+0.49748743718593i, 0+0.527638190954774i, 0+0.557788944723618i, 0+0.587939698492462i, 0+0.618090452261306i, 0+0.648241206030151i, 0+0.678391959798995i, 0+0.708542713567839i, 0+0.738693467336683i, 0+0.768844221105527i, 0+0.798994974874372i, 0+0.829145728643216i, 0+0.85929648241206i, 0+0.889447236180904i, 0+0.919597989949748i, 0+0.949748743718593i, 0+0.979899497487437i, 0+1.01005025125628i, 0+1.04020100502513i, 0+1.07035175879397i, 0+1.10050251256281i, 0+1.13065326633166i, 0+1.1608040201005i, 0+1.19095477386935i, 0+1.22110552763819i, 0+1.25125628140704i, 0+1.28140703517588i, 0+1.31155778894472i, 0+1.34170854271357i, 0+1.37185929648241i, 0+1.40201005025126i, 0+1.4321608040201i, 0+1.46231155778894i, 0+1.49246231155779i, 0+1.52261306532663i, 0+1.55276381909548i, 0+1.58291457286432i, 0+1.61306532663317i, 0+1.64321608040201i, 0+1.67336683417085i, 0+1.7035175879397i, 0+1.73366834170854i, 0+1.76381909547739i, 0+1.79396984924623i, 0+1.82412060301507i, 0+1.85427135678392i, 0+1.88442211055276i, 0+1.91457286432161i, 0+1.94472361809045i, 0+1.9748743718593i, 0+2.00502512562814i, 0+2.03517587939698i, 0+2.06532663316583i, 0+2.09547738693467i, 0+2.12562814070352i, 0+2.15577889447236i, 0+2.18592964824121i, 0+2.21608040201005i, 0+2.24623115577889i, 0+2.27638190954774i, 0+2.30653266331658i, 0+2.33668341708543i, 0+2.36683417085427i, 0+2.39698492462312i, 0+2.42713567839196i, 0+2.4572864321608i, 0+2.48743718592965i, 0+2.51758793969849i, 0+2.54773869346734i, 0+2.57788944723618i, 0+2.60804020100502i, 0+2.63819095477387i, 0+2.66834170854271i, 0+2.69849246231156i, 0+2.7286432160804i, 0+2.75879396984925i, 0+2.78894472361809i, 0+2.81909547738693i, 0+2.84924623115578i, 0+2.87939698492462i, 0+2.90954773869347i, 0+2.93969849246231i, 0+2.96984924623116i, 0+3i));cosh(argv[[1]]);"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cummax.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cummax.java index 4189fdf32f307f28d35ff96915bac9999d01d0a0..43352fd855913cabdbe011d89dfc3529576be380 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cummax.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cummax.java @@ -45,7 +45,7 @@ public class TestBuiltin_cummax extends TestBase { @Test public void testcummax6() { - assertEval(Ignored.Unknown, "argv <- list(NULL);cummax(argv[[1]]);"); + assertEval("argv <- list(NULL);cummax(argv[[1]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cummin.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cummin.java index b6ce4958fe52af2d54dc8e347a282872202314ec..247a4b6c9a2a773291727a47eadee3c6dc663b1b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cummin.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cummin.java @@ -50,7 +50,7 @@ public class TestBuiltin_cummin extends TestBase { @Test public void testcummin7() { - assertEval(Ignored.Unknown, "argv <- list(NULL);cummin(argv[[1]]);"); + assertEval("argv <- list(NULL);cummin(argv[[1]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cumprod.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cumprod.java index 35b1f827aac1fe522ec844386eb8efa1eb25df17..033eb601b4781e29fe58f2a2741846d6c8d1f077 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cumprod.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cumprod.java @@ -24,8 +24,7 @@ public class TestBuiltin_cumprod extends TestBase { @Test public void testcumprod2() { - assertEval(Ignored.Unknown, - "argv <- list(c(0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i));cumprod(argv[[1]]);"); + assertEval("argv <- list(c(0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i, 0.2853725+0.3927816i));cumprod(argv[[1]]);"); } @Test @@ -56,7 +55,7 @@ public class TestBuiltin_cumprod extends TestBase { @Test public void testcumprod8() { - assertEval(Ignored.Unknown, "argv <- list(NULL);cumprod(argv[[1]]);"); + assertEval("argv <- list(NULL);cumprod(argv[[1]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cumsum.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cumsum.java index 0bd4a01807095e3cf9ad574533733b4f47c878aa..a4be02abad4a1a1228373a139caefe8b7884c9f1 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cumsum.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cumsum.java @@ -39,7 +39,7 @@ public class TestBuiltin_cumsum extends TestBase { @Test public void testcumsum5() { - assertEval(Ignored.Unknown, "argv <- list(NULL);cumsum(argv[[1]]);"); + assertEval("argv <- list(NULL);cumsum(argv[[1]]);"); } @Test @@ -108,7 +108,7 @@ public class TestBuiltin_cumsum extends TestBase { assertEval(Ignored.Unknown, "{ cumsum(c(1,2,3,0/0,5)) }"); assertEval(Ignored.Unknown, "{ cumsum(c(1,0/0,5+1i)) }"); - assertEval(Ignored.Unknown, "{ cumsum(as.raw(1:6)) }"); + assertEval("{ cumsum(as.raw(1:6)) }"); // FIXME 1e+308 assertEval(Ignored.Unknown, "{ cumsum(rep(1e308, 3) ) }"); // FIXME 1e+308 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 a8749fef6f05bb5dd1b7de8c1dc323d4a8b6db34..5df001b1eced2ec044ca27df289421189658b8b5 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 @@ -226,7 +226,7 @@ public class TestBuiltin_deparse extends TestBase { @Test public void testdeparse40() { - assertEval(Ignored.Unknown, "argv <- list(logical(0), logical(0), FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); + assertEval(Output.IgnoreWarningContext, "argv <- list(logical(0), logical(0), FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_det.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_det.java index 57692a786023c32f98daf21e9277fc8da9689abf..03c916578780d4c15100169745c7226f424c5881 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_det.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_det.java @@ -19,14 +19,12 @@ public class TestBuiltin_det extends TestBase { @Test public void testdet1() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(FALSE, TRUE, TRUE, FALSE), .Dim = c(2L, 2L), .Dimnames = list(c('A', 'B'), c('A', 'B'))), TRUE); .Internal(det_ge_real(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(c(FALSE, TRUE, TRUE, FALSE), .Dim = c(2L, 2L), .Dimnames = list(c('A', 'B'), c('A', 'B'))), TRUE); .Internal(det_ge_real(argv[[1]], argv[[2]]))"); } @Test public void testdet2() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(TRUE, TRUE, TRUE, TRUE), .Dim = c(2L, 2L), .Dimnames = list(c('A', 'B'), c('A', 'B'))), TRUE); .Internal(det_ge_real(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(c(TRUE, TRUE, TRUE, TRUE), .Dim = c(2L, 2L), .Dimnames = list(c('A', 'B'), c('A', 'B'))), TRUE); .Internal(det_ge_real(argv[[1]], argv[[2]]))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dimnamesassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dimnamesassign.java index 824deb8ec7e81a895f16d6e0b74c489ac068f454..f592d11f570e6158b74a8d0baa19023e79463866 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dimnamesassign.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dimnamesassign.java @@ -74,8 +74,7 @@ public class TestBuiltin_dimnamesassign extends TestBase { @Test public void testdimnamesassign12() { - assertEval(Ignored.Unknown, - "argv <- list(structure(list(fair = c(326L, 688L, 343L, 98L), red = c(38L, 116L, 84L, 48L), medium = c(241L, 584L, 909L, 403L), dark = c(110L, 188L, 412L, 681L), black = c(3L, 4L, 26L, 85L)), .Names = c('fair', 'red', 'medium', 'dark', 'black'), class = 'data.frame', row.names = c('blue', 'light', 'medium', 'dark')), value = list(c('blue', 'light', 'medium', 'dark'), c('F', 'R', 'M', 'D', 'B')));`dimnames<-`(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(list(fair = c(326L, 688L, 343L, 98L), red = c(38L, 116L, 84L, 48L), medium = c(241L, 584L, 909L, 403L), dark = c(110L, 188L, 412L, 681L), black = c(3L, 4L, 26L, 85L)), .Names = c('fair', 'red', 'medium', 'dark', 'black'), class = 'data.frame', row.names = c('blue', 'light', 'medium', 'dark')), value = list(c('blue', 'light', 'medium', 'dark'), c('F', 'R', 'M', 'D', 'B')));`dimnames<-`(argv[[1]],argv[[2]]);"); } @Test @@ -92,4 +91,9 @@ public class TestBuiltin_dimnamesassign extends TestBase { public void testdimnamesassign15() { assertEval("argv <- list(structure(c('NULL', 'double', 'integer', 'complex', 'list', 'list', 'pairlist', 'builtin', 'closure', 'symbol', 'symbol', 'language', 'language', 'symbol', 'symbol', 'NULL', 'double', 'integer', 'complex', 'list', 'list', 'pairlist', 'function', 'function', 'symbol', 'symbol', 'language', 'language', 'symbol', 'symbol', 'NULL', 'numeric', 'numeric', 'complex', 'list', 'list', 'pairlist', 'function', 'function', 'name', 'name', 'call', '(', 'name', 'name'), .Dim = c(15L, 3L), .Dimnames = list( c('NULL', '1', '1:1', '1i', 'list(1)', 'data.frame(x = 1)', 'pairlist(pi)', 'c', 'lm', 'formals(lm)[[1]]', 'formals(lm)[[2]]', 'y ~ x', 'expression((1))[[1]]', '(y ~ x)[[1]]', 'expression(x <- pi)[[1]][[1]]'), c('typeof(.)', 'storage.mode(.)', 'mode(.)'))), value = list(c('NULL', '1', '1:1', '1i', 'list(1)', 'data.frame(x = 1)', 'pairlist(pi)', 'c', 'lm', 'formals(lm)[[1]]', 'formals(lm)[[2]]', 'y ~ x', 'expression((1))[[1]]', '(y ~ x)[[1]]', 'expression(x <- pi)[[1]][[1]]'), c('typeof(.)', 'storage.mode(.)', 'mode(.)')));`dimnames<-`(argv[[1]],argv[[2]]);"); } + + @Test + public void testDimnamesAssign() { + assertEval("{ x<-data.frame(c(1,2),c(3,4)); dimnames(x) <- list(c(\"A\", \"B\"), c(\"C\", \"D\")); 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 f2a56bb64279834f67bf8aaf1561f73aab866c94..3040237600c6d490b85893e20465e5eec7e6755f 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 @@ -130,5 +130,10 @@ public class TestBuiltin_duplicated extends TestBase { assertEval(Output.IgnoreWarningContext, "{ duplicated(c(1,2,3,2), incomparables = c(2+6i)) }"); assertEval("{ duplicated(NULL, 0); }"); + + assertEval("{ x<-quote(f(7, 42)); duplicated(x) }"); + assertEval("{ x<-function() 42; duplicated(x) }"); + assertEval(Output.IgnoreErrorContext, "{ duplicated(c(1,2,1), incomparables=function() 42) }"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_enc2native.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_enc2native.java index e1206744b91190bc66dce716ff7ff7fa96e95b51..b271802aa3c77bd6c589e381a4ae095bc47802f2 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_enc2native.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_enc2native.java @@ -31,4 +31,10 @@ public class TestBuiltin_enc2native extends TestBase { public void testenc2native4() { assertEval("argv <- list('José Pinheiro [aut] (S version)');enc2native(argv[[1]]);"); } + + @Test + public void testInvalidArguments() { + // Note: GnuR has typo in the message + assertEval(Output.IgnoreErrorMessage, "enc2native(42);"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_enc2utf8.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_enc2utf8.java index 9cafe3f976507a09931be1333ff305a0da1343f7..de6cf882ae70d601ef7f36653d0fe86a232bca62 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_enc2utf8.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_enc2utf8.java @@ -41,4 +41,10 @@ public class TestBuiltin_enc2utf8 extends TestBase { public void testenc2utf86() { assertEval("argv <- list(NA_character_);do.call('enc2utf8', argv)"); } + + @Test + public void testInvalidArguments() { + // Note: GnuR has typo in the message + assertEval(Output.IgnoreErrorMessage, "enc2utf8(42);"); + } } 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 db14b641246e7d02ecfab7360daf4b07a619059f..af8ec8a7f429a83153e298e6e3d2ab61a2259548 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 @@ -23,7 +23,14 @@ public class TestBuiltin_environmentassign extends TestBase { assertEval("{ e1 <- new.env(); e2 <- new.env(); environment(e1) <- e2 }"); assertEval("{ e1 <- new.env(); environment(e1) <- 3 }"); + assertEval("{ e1 <- 1; environment(e1) <- NULL }"); + assertEval("{ e1 <- 1; e2 <- new.env(); environment(e1) <- e2 }"); + assertEval("{ e1 <- 1; environment(e1) <- 3 }"); + assertEval("{ f <- function() {}; e1 <- new.env(); environment(f) <- e1 }"); + assertEval("{ f <- function() {}; environment(f) <- NULL }"); 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() }"); } } 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 25c20c74c52029b53faa5d54bf503906b1e7a69c..adeaff0eebe559866fae460c9be9a10a0586836e 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 @@ -41,6 +41,10 @@ public class TestBuiltin_eval extends TestBase { assertEval("{ g<-function(y) { f<-function(x) { x }; substitute(f(y)) } ; eval(g(42)) }"); assertEval("{ eval({ xx <- pi; xx^2}) ; xx }"); + assertEval("eval('foo')"); + assertEval(Output.IgnoreErrorContext, "eval(as.symbol('foo'))"); + assertEval("eval(as.symbol('baseenv'))"); + // should print two values, xx^2 and xx assertEval("eval({ xx <- pi; xx^2}) ; xx"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exists.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exists.java index d3fb8b2e25cd29b3de228de0e83183c975ca76f4..9d0d024d3b85973594eafdb287b2a7a11f0da737 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exists.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exists.java @@ -21,5 +21,9 @@ public class TestBuiltin_exists extends TestBase { @Test public void testexists1() { assertEval("argv <- structure(list(x = '.Device'), .Names = 'x');do.call('exists', argv)"); + assertEval("exists('somethingthatdoesnotexist123456789')"); + assertEval("exists('.Device', inherit=FALSE)"); + assertEval("x <- 42; exists('x', mode='numeric')"); + assertEval("x <- '42'; exists('x', mode='numeric')"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formals.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formals.java index 0cec14139f90878754fd089d30db96edfcdf8d77..ca049b700fa0d8a8bc422856007c564d5e34717f 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formals.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formals.java @@ -24,18 +24,17 @@ public class TestBuiltin_formals extends TestBase { @Test public void testformals2() { - assertEval(Ignored.Unknown, "argv <- list(logical(0)); .Internal(formals(argv[[1]]))"); + assertEval("argv <- list(logical(0)); .Internal(formals(argv[[1]]))"); } @Test public void testformals3() { - assertEval(Ignored.Unknown, "argv <- list(structure(numeric(0), .Dim = c(0L, 0L))); .Internal(formals(argv[[1]]))"); + assertEval("argv <- list(structure(numeric(0), .Dim = c(0L, 0L))); .Internal(formals(argv[[1]]))"); } @Test public void testformals4() { - assertEval(Ignored.Unknown, - "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]]))"); + assertEval("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]]))"); } @Test 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 dbf55bd954e4d691b0d2092543110d38a9aa7fe5..eaaffe5711ac037b4c58ad78ec2e3133da8e8299 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 @@ -242,8 +242,7 @@ public class TestBuiltin_format extends TestBase { @Test public void testformat46() { - assertEval(Ignored.Unknown, - "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]]))"); + assertEval("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]]))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_get.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_get.java index 7c028c4f80e8b3bf7d5609d16c31e5b44e58d8c3..71ad84e6ef169c30f8eeb6d78d6cec134f20346e 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_get.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_get.java @@ -24,12 +24,12 @@ public class TestBuiltin_get extends TestBase { assertEval("{y<-function(){y<-2;get(\"y\",mode=\"integer\",inherits=FALSE);get(\"y\",mode=\"integer\",inherits=FALSE)};y();}"); assertEval("{y<-function(){y<-2;get(\"y\",mode=\"double\")};y();}"); assertEval("{y<-function(){y<-2;get(\"y\",mode=\"double\",inherits=FALSE)};y();}"); - assertEval(Output.IgnoreErrorContext, "{ get(\"dummy\") }"); - assertEval(Output.IgnoreErrorContext, "{ x <- 33 ; f <- function() { if (FALSE) { x <- 22 } ; get(\"x\", inherits = FALSE) } ; f() }"); - assertEval(Output.IgnoreErrorContext, "{ x <- 33 ; f <- function() { get(\"x\", inherits = FALSE) } ; f() }"); + assertEval("{ get(\"dummy\") }"); + assertEval("{ x <- 33 ; f <- function() { if (FALSE) { x <- 22 } ; get(\"x\", inherits = FALSE) } ; f() }"); + assertEval("{ x <- 33 ; f <- function() { get(\"x\", inherits = FALSE) } ; f() }"); assertEval("{ get(\".Platform\", globalenv())$endian }"); assertEval("{ get(\".Platform\")$endian }"); - assertEval(Output.IgnoreErrorContext, "{y<-function(){y<-2;get(\"y\",mode=\"closure\",inherits=FALSE);};y();}"); + assertEval("{y<-function(){y<-2;get(\"y\",mode=\"closure\",inherits=FALSE);};y();}"); // behavior specific to RS4Object as environment: assertEval("setClass('foo', representation(x='numeric')); f <- new('foo'); e <- new.env(); e$x <- 1; attr(f, '.xData') <- e; get('x', envir=f)"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gregexpr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gregexpr.java index 32e9867ee52e84d3ea7a31f20410ae095cd518eb..1aba62e2999b9cd6221a8453a40b3edbde6da975 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gregexpr.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gregexpr.java @@ -103,5 +103,15 @@ public class TestBuiltin_gregexpr extends TestBase { assertEval(Ignored.Unknown, "gregexpr(\"e\",c(\"arm\",\"foot\",\"lefroo\", \"bafoobar\"))"); // NOTE: this is without attributes assertEval(Ignored.Unknown, "gregexpr(\"(a)[^a]\\\\1\", c(\"andrea apart\", \"amadeus\", NA))"); + + assertEval("{ x<-gregexpr(\"foo\", c(\"bar foo foo\", \"foo\"), fixed=T); as.integer(c(x[[1]], x[[2]])) }"); + assertEval("{ x<-gregexpr(\"foo\", c(\"bar foo foo\", \"foo\"), fixed=F); as.integer(c(x[[1]], x[[2]])) }"); + assertEval("{ x<-gregexpr(\"foo\", c(\"bar foo foo\", \"foo\"), fixed=T); list(attr(x[[1]], \"match.length\"), attr(x[[2]], \"match.length\")) }"); + assertEval("{ x<-gregexpr(\"foo\", c(\"bar foo foo\", \"foo\"), fixed=F); list(attr(x[[1]], \"match.length\"), attr(x[[2]], \"match.length\")) }"); + + assertEval("{ .Internal(gregexpr(7, \"42\", F, F, F, F)) }"); + assertEval("{ .Internal(gregexpr(character(), \"42\", F, F, F, F)) }"); + assertEval("{ .Internal(gregexpr(\"7\", 42, F, F, F, F)) }"); + } } 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 c68b2c44c415dada66799cc67e2a44283c585754..c3b9ada54787a3f1327676af89aff57ee31372d6 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 @@ -82,6 +82,11 @@ public class TestBuiltin_grep extends TestBase { assertEval("{ txt<-c(\"is\", \"intended\", \"to\", \"guarantee\", \"your\", \"freedom\"); grep(\"[gu]\", txt) }"); assertEval("{ txt<-c(\"1+1i\", \"7\", \"42.1\", \"7+42i\"); grep(\"[0-9].*[-+][0-9].*i$\", txt) }"); assertEval("{ txt<-c(\"rai\", \"ira\", \"iri\"); grep(\"i$\", txt) }"); + + assertEval("{ .Internal(grep(7, \"7\", F, F, F, F, F, F)) }"); + assertEval("{ .Internal(grep(character(), \"7\", F, F, F, F, F, F)) }"); + assertEval("{ .Internal(grep(\"7\", 7, F, F, F, F, F, F)) }"); + } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grepl.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grepl.java index 683177414fe692fe7dbe24f69288e5ff609d3f58..1e2e74500566da9a3ca4116c2d461072c978c3dc 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grepl.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grepl.java @@ -73,7 +73,11 @@ public class TestBuiltin_grepl extends TestBase { } @Test - public void testGrep() { + public void testGrepl() { assertEval("{ txt<-c(\"arm\",\"foot\",\"lefroo\", \"bafoobar\"); grepl(\"foo\", txt) }"); + + assertEval("{ .Internal(grepl(7, \"7\", F, F, F, F, F, F)) }"); + assertEval("{ .Internal(grepl(character(), \"7\", F, F, F, F, F, F)) }"); + assertEval("{ .Internal(grepl(\"7\", 7, F, F, F, F, F, F)) }"); } } 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 74b77a503b5c982fe96b05ef6b88025412202c4c..3f8abf76cf0e6cf55490d592b7e2fc4ebb83e570 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 @@ -170,7 +170,7 @@ public class TestBuiltin_gsub extends TestBase { } @Test - public void testSub() { + public void testGsub() { assertEval("{ gsub(\"a\",\"aa\", \"prague alley\") }"); assertEval("{ gsub(\"a\",\"aa\", \"prAgue alley\") }"); assertEval("{ gsub(\"a\",\"aa\", \"prague alley\", fixed=TRUE) }"); @@ -180,5 +180,11 @@ public class TestBuiltin_gsub extends TestBase { assertEval("{ gsub(\"h\",\"\", c(\"hello\", \"hi\", \"bye\")) }"); assertEval("{ gsub(\"h\",\"\", c(\"hello\", \"hi\", \"bye\"), fixed=TRUE) }"); assertEval(Ignored.Unknown, "{ gsub(\"a\",\"aa\", \"prAgue alley\", ignore.case=TRUE) }"); + + assertEval("{ .Internal(gsub(7, \"42\", \"7\", F, F, F, F)) }"); + assertEval("{ .Internal(gsub(character(), \"42\", \"7\", F, F, F, F)) }"); + assertEval("{ .Internal(gsub(\"7\", 42, \"7\", F, F, F, F)) }"); + assertEval("{ .Internal(gsub(\"7\", character(), \"7\", F, F, F, F)) }"); + assertEval("{ .Internal(gsub(\"7\", \"42\", 7, F, F, F, F)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_iconv.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_iconv.java index 0ce698940de8f884e5b26023f95f9249796a32d5..c05827b501e3e65d7d967e785de15f6affd22345 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_iconv.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_iconv.java @@ -63,4 +63,15 @@ public class TestBuiltin_iconv extends TestBase { assertEval(Ignored.Unknown, "argv <- list(structure(c('Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance'), .Names = c('Q1_MISSING_NONE', 'Q1_MISSING_1', 'Q1_MISSING_2', 'Q1_MISSING_3', 'Q1_MISSING_RANGE', 'Q1_MISSING_LOW', 'Q1_MISSING_HIGH', 'Q1_MISSING_RANGE_1', 'Q1_MISSING_LOW_1', 'Q1_MISSING_HIGH_1')), 'latin1', '', NA_character_, TRUE, FALSE); .Internal(iconv(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]]))"); } + + @Test + public void testIconv() { + assertEval("{ .Internal(iconv(7, \"latin1\", \"ASCII\", \"42\", T, F)) }"); + assertEval("{ .Internal(iconv(\"7\", character(), \"ASCII\", \"42\", T, F)) }"); + assertEval("{ .Internal(iconv(\"7\", c(\"latin1\", \"latin1\"), \"ASCII\", \"42\", T, F)) }"); + assertEval("{ .Internal(iconv(\"7\", \"latin1\", c(\"ASCII\", \"ASCII\"), \"42\", T, F)) }"); + assertEval("{ .Internal(iconv(\"7\", \"latin1\", character(), \"42\", T, F)) }"); + assertEval("{ .Internal(iconv(\"7\", \"latin1\", \"ASCII\", 42, T, F)) }"); + assertEval("{ .Internal(iconv(\"7\", \"latin1\", \"ASCII\", character(), T, F)) }"); + } } 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 0e779d4794afcdde98c9dbcf4df7f5029de2d604..77fcee218b858d8dae875e1f758d5247b4cd87c4 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 @@ -209,8 +209,9 @@ public class TestBuiltin_inherits extends TestBase { assertEval("{ inherits(getClass(\"ClassUnionRepresentation\"), \"classRepresentation\") }"); - // Fails because of exact string matching in error message. - assertEval(Ignored.Unknown, "{x <- 10;class(x) <- c(\"a\", \"b\");inherits(x, 2, c(TRUE)) ;}"); - assertEval(Ignored.Unknown, "{x <- 10;class(x) <- c(\"a\", \"b\");inherits(x, \"a\", 1) ;}"); + 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("inherits(NULL, 'NULL')"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isNamespaceEnv.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isNamespaceEnv.java index 48d1b4114a92094dc95f008b58d9e98a7e820b2d..2769b43b83c7e694c6727f116d50f293f6250591 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isNamespaceEnv.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isNamespaceEnv.java @@ -19,17 +19,16 @@ public class TestBuiltin_isNamespaceEnv extends TestBase { @Test public void testisNamespaceEnv1() { - assertEval(Ignored.Unknown, "argv <- list(FALSE); .Internal(isNamespaceEnv(argv[[1]]))"); + assertEval("argv <- list(FALSE); .Internal(isNamespaceEnv(argv[[1]]))"); } @Test public void testisNamespaceEnv2() { - assertEval(Ignored.Unknown, "argv <- list(structure(numeric(0), .Dim = c(0L, 0L))); .Internal(isNamespaceEnv(argv[[1]]))"); + assertEval("argv <- list(structure(numeric(0), .Dim = c(0L, 0L))); .Internal(isNamespaceEnv(argv[[1]]))"); } @Test public void testisNamespaceEnv3() { - assertEval(Ignored.Unknown, - "argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = 'data.frame')); .Internal(isNamespaceEnv(argv[[1]]))"); + assertEval("argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = 'data.frame')); .Internal(isNamespaceEnv(argv[[1]]))"); } } 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 68b9a80272e0df9d2732cbd8b702aeea6439d482..e7290d237c5fb23470405701ad86070938ec2687 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 @@ -29,8 +29,7 @@ public class TestBuiltin_isna extends TestBase { @Test public void testisna3() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(17L, 18L, 18L, 18L), .Dim = 4L, .Dimnames = structure(list(N = c('0.0cwt', '0.2cwt', '0.4cwt', '0.6cwt')), .Names = 'N')));is.na(argv[[1]]);"); + assertEval("argv <- list(structure(c(17L, 18L, 18L, 18L), .Dim = 4L, .Dimnames = structure(list(N = c('0.0cwt', '0.2cwt', '0.4cwt', '0.6cwt')), .Names = 'N')));is.na(argv[[1]]);"); } @Test @@ -50,8 +49,7 @@ public class TestBuiltin_isna extends TestBase { @Test public void testisna8() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(23L, 24L, 47L, 48L, 71L, 72L, 95L, 96L, 119L, 120L), .Dim = c(2L, 5L), .Dimnames = list(NULL, c('V5', 'V6', 'V7', 'V8', 'V9'))));is.na(argv[[1]]);"); + assertEval("argv <- list(structure(c(23L, 24L, 47L, 48L, 71L, 72L, 95L, 96L, 119L, 120L), .Dim = c(2L, 5L), .Dimnames = list(NULL, c('V5', 'V6', 'V7', 'V8', 'V9'))));is.na(argv[[1]]);"); } @Test @@ -177,8 +175,7 @@ public class TestBuiltin_isna extends TestBase { @Test public void testisna34() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c('Min. : 1.00 ', '1st Qu.: 9.00 ', 'Median :18.00 ', 'Mean :14.74 ', '3rd Qu.:20.00 ', 'Max. :23.00 ', NA, 'Min. :5.000 ', '1st Qu.:5.300 ', 'Median :6.100 ', 'Mean :6.084 ', '3rd Qu.:6.600 ', 'Max. :7.700 ', NA, '117 : 5 ', '1028 : 4 ', '113 : 4 ', '112 : 3 ', '135 : 3 ', '(Other):147 ', 'NAs : 16 ', 'Min. : 0.50 ', '1st Qu.: 11.32 ', 'Median : 23.40 ', 'Mean : 45.60 ', '3rd Qu.: 47.55 ', 'Max. :370.00 ', NA, 'Min. :0.00300 ', '1st Qu.:0.04425 ', 'Median :0.11300 ', 'Mean :0.15422 ', '3rd Qu.:0.21925 ', 'Max. :0.81000 ', NA), .Dim = c(7L, 5L), .Dimnames = list(c('', '', '', '', '', '', ''), c(' event', ' mag', ' station', ' dist', ' accel')), class = 'table'));is.na(argv[[1]]);"); + assertEval("argv <- list(structure(c('Min. : 1.00 ', '1st Qu.: 9.00 ', 'Median :18.00 ', 'Mean :14.74 ', '3rd Qu.:20.00 ', 'Max. :23.00 ', NA, 'Min. :5.000 ', '1st Qu.:5.300 ', 'Median :6.100 ', 'Mean :6.084 ', '3rd Qu.:6.600 ', 'Max. :7.700 ', NA, '117 : 5 ', '1028 : 4 ', '113 : 4 ', '112 : 3 ', '135 : 3 ', '(Other):147 ', 'NAs : 16 ', 'Min. : 0.50 ', '1st Qu.: 11.32 ', 'Median : 23.40 ', 'Mean : 45.60 ', '3rd Qu.: 47.55 ', 'Max. :370.00 ', NA, 'Min. :0.00300 ', '1st Qu.:0.04425 ', 'Median :0.11300 ', 'Mean :0.15422 ', '3rd Qu.:0.21925 ', 'Max. :0.81000 ', NA), .Dim = c(7L, 5L), .Dimnames = list(c('', '', '', '', '', '', ''), c(' event', ' mag', ' station', ' dist', ' accel')), class = 'table'));is.na(argv[[1]]);"); } @Test @@ -198,14 +195,12 @@ public class TestBuiltin_isna extends TestBase { @Test public void testisna38() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(2L, 6L, 2L, 5L, 4L, 2L, 5L, 4L), .Dim = 8L, .Dimnames = structure(list(statef = c('act', 'nsw', 'nt', 'qld', 'sa', 'tas', 'vic', 'wa')), .Names = 'statef'), class = 'table'));is.na(argv[[1]]);"); + assertEval("argv <- list(structure(c(2L, 6L, 2L, 5L, 4L, 2L, 5L, 4L), .Dim = 8L, .Dimnames = structure(list(statef = c('act', 'nsw', 'nt', 'qld', 'sa', 'tas', 'vic', 'wa')), .Names = 'statef'), class = 'table'));is.na(argv[[1]]);"); } @Test public void testisna39() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(2, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0), .Dim = 3:4, .Dimnames = structure(list(x1 = c('a', 'b', 'c'), x2 = c('a', 'b', 'c', NA)), .Names = c('x1', 'x2')), class = c('xtabs', 'table')));is.na(argv[[1]]);"); + assertEval("argv <- list(structure(c(2, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0), .Dim = 3:4, .Dimnames = structure(list(x1 = c('a', 'b', 'c'), x2 = c('a', 'b', 'c', NA)), .Names = c('x1', 'x2')), class = c('xtabs', 'table')));is.na(argv[[1]]);"); } @Test @@ -254,9 +249,10 @@ public class TestBuiltin_isna extends TestBase { 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(is.na))"); + assertEval("is.na(is.na)"); // Note: is.na.data.frame calls do.call("cbind", lapply(x, "is.na")) - there is the error + // Probably the same error as in testisna13 assertEval(Ignored.Unimplemented, "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_isunsorted.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isunsorted.java index a1981e67d95939c53b3d1ca2e4e458b0cdc3aa56..be6652d29a371a85ce41558f533d0eaf7bf1cdb9 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 @@ -95,5 +95,8 @@ public class TestBuiltin_isunsorted extends TestBase { public void testIsUnsorted() { assertEval("{ is.unsorted(c(1,2,3,4)) }"); assertEval("{ is.unsorted(c(1,2,6,4)) }"); + 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) }"); } } 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 01442b5c235bfd911bb6a53581e2fe8c8d7b0c67..4cfb24acda41b9dd827e6c07712462b071318f90 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 @@ -199,5 +199,7 @@ 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);}"); } } 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 91ea3fcda94edc7cb468490f7c662f46f45c5ffd..72228b0de6e2cac4b011399b7b08eb40007e2889 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 @@ -31,6 +31,8 @@ public class TestBuiltin_lapply extends TestBase { assertEval("{ lapply(1:3, sum, 2) }"); assertEval("{ x <- list(a=1:10, b=1:20) ; lapply(x, sum) }"); 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)) }"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lengthassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lengthassign.java index 70d22371b51a2c9efb09f5a5d2fca03aced78cd8..d8670d083b79fe18047b381ec55b35ebedcd8bd9 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lengthassign.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lengthassign.java @@ -46,7 +46,7 @@ public class TestBuiltin_lengthassign extends TestBase { public void testlengthassign6() { assertEval("argv <- list(list(), value = 0L);`length<-`(argv[[1]],argv[[2]]);"); - assertEval(Ignored.Unknown, "argv <- structure(list(1:3, value = TRUE), .Names = c('', 'value'));do.call('length<-', argv)"); + assertEval(Output.IgnoreErrorContext, "argv <- structure(list(1:3, value = TRUE), .Names = c('', 'value'));do.call('length<-', argv)"); } @Test @@ -67,4 +67,12 @@ public class TestBuiltin_lengthassign extends TestBase { assertEval("{ x<-c(a=7, b=42); length(x)<-1; x }"); assertEval("{ x<-NULL; length(x)<-2; x }"); } + + @Test + public void testArgsCasts() { + assertEval("{ x<-quote(a); length(x)<-2 }"); + assertEval("{ x<-c(42, 1); length(x)<-'3'; x }"); + assertEval("{ x<-c(42, 1); length(x)<-3.1; x }"); + assertEval("{ x<-c(42, 1); length(x)<-c(1,2) }"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lengths.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lengths.java new file mode 100644 index 0000000000000000000000000000000000000000..fb7a94527e29dfcfa2a75ea547fc9403246b036f --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lengths.java @@ -0,0 +1,55 @@ +/* + * 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.test.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestBuiltin_lengths extends TestBase { + @Test + public void basics() { + assertEval("lengths(c(1,2,3))"); + assertEval("lengths(1:11)"); + assertEval("lengths(list(1, c(1,2), 1:3))"); + assertEval("lengths(list(1, list(1, c(1,2)), 1:3))"); + assertEval("lengths(NULL)"); + } + + @Test + public void withNames() { + assertEval("lengths(list(a=1, b=c(1,2)))"); + assertEval("lengths(list(a=1, b=c(1,2)), use.names=FALSE)"); + assertEval("x<-c(1,2); names(x) <- c('a', 'b'); lengths(x)"); + assertEval("x<-c(1,2); names(x) <- c('a', 'b'); lengths(x, use.names=FALSE)"); + // dimnames are not used: + assertEval("lengths(matrix(1:4, nrow=2, ncol=2, dimnames=list(c('a', 'b'), c('d', 'e'))))"); + } + + @Test + public void wrongArgs() { + assertEval(Output.IgnoreErrorContext, "lengths(quote(a))"); + assertEval(Output.IgnoreErrorContext, "lengths(42, use.names='as')"); + } +} 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 a6555db15ae05893b486449712dab6cd54dce9c1..af849991e4c06e018ac519a6507c480da6238a6b 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 @@ -347,8 +347,7 @@ public class TestBuiltin_list extends TestBase { @Test public void testlist62() { - assertEval(Ignored.Unknown, - "argv <- list(values = c(-2572.90550008339+0i, -915.064609071159+0i, -456.632018115023+0i, 419.980933101553+0i, -366.745362912885+0i, -308.301779528581+0i, -258.104614655539+0i, -208.43876984087+0i, -174.152165416129+0i, 166.131403923756+0i, -153.932564395224+31.248756965275i, -153.932564395224-31.248756965275i, -145.261798316303+0i, -140.969649074553+0i, -109.026224585292+37.27313202252i, -109.026224585292-37.27313202252i, -95.4200045428049+0i, -94.2845517186135+0i, 93.6287479850051+0i, -83.7083948970612+39.7221174209657i, -83.7083948970612-39.7221174209657i, -89.7405335285911+14.6972603541884i, -89.7405335285911-14.6972603541884i, -90.4677652619726+0i, 80.9227484547009+0i, -79.2808369338756+0i, -67.7641499054793+34.4882180369511i, -67.7641499054793-34.4882180369511i, -74.7131802385517+0i, -72.7892236613541+0i, -70.8748882290923+0i, -65.326216345093+24.6325729497989i, -65.326216345093-24.6325729497989i, -65.6613463045206+12.2012477360608i, -65.6613463045206-12.2012477360608i, -64.009437139127+0i, -53.8555784147338+28.3814233344012i, -53.8555784147338-28.3814233344012i, -60.372612826631+0i, -55.598407412763+0i, -53.8337490558365+13.1765372798343i, -53.8337490558365-13.1765372798343i, -48.7010835501729+24.5244827641945i, -48.7010835501729-24.5244827641945i, -51.620171425175+0i, -49.1047272072286+7.0804434036442i, -49.1047272072286-7.0804434036442i, -44.0755122578262+21.8965512206582i, -44.0755122578262-21.8965512206582i, -47.6686025497685+0i, -47.0350049752776+0i, 43.2054741656531+0i, -42.0546965543942+0i, -41.4311176038551+0i, -36.4574226401686+16.1634950480082i, -36.4574226401686-16.1634950480082i, -39.2901755793811+0i, -36.5376333751307+11.2152902727145i, -36.5376333751307-11.2152902727145i, -38.0398197891428+0i, -32.9946255929378+12.9867445602001i, -32.9946255929378-12.9867445602001i, -34.7321001383969+0i, -32.0667502593492+12.342590095597i, -32.0667502593492-12.342590095597i, -27.2830437098322+11.6992356475951i, -27.2830437098322-11.6992356475951i, -29.1247671355682+2.0847233845627i, -29.1247671355682-2.0847233845627i, -28.1216021055426+0i, -27.0745572919711+0i, 26.1565478253913+0i, -23.4210302095847+1.8723763695687i, -23.4210302095847-1.8723763695687i, 20.782836979896+0i, 16.5058357149619+0i, -15.9316203363047+0i, 13.2377600042936+0i, -11.9119569568831+0i, -11.1832867499603+0i, 8.99100195370794+0i, 7.62805946796798+0i, -7.44159556589097+0i, -6.46699019595805+0i, 5.57838460483725+0i, 5.07382264677001+0i, -4.77172378340461+0i, 4.21976444063592+0i, -2.86123099075901+0i, -2.69814683135512+0i, -2.29820560404041+0i, 2.05951624519943+0i, -1.8306332549612+0i, 1.66021670517454+0i, 1.03505989993491+0i, -0.773887754953459+0i, -0.416100454072758+0i, 0.213086170361661+0i, -3.42336062193255e-06+0i, 3.42336057523814e-06+0i), vectors = NULL);list(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(values = c(-2572.90550008339+0i, -915.064609071159+0i, -456.632018115023+0i, 419.980933101553+0i, -366.745362912885+0i, -308.301779528581+0i, -258.104614655539+0i, -208.43876984087+0i, -174.152165416129+0i, 166.131403923756+0i, -153.932564395224+31.248756965275i, -153.932564395224-31.248756965275i, -145.261798316303+0i, -140.969649074553+0i, -109.026224585292+37.27313202252i, -109.026224585292-37.27313202252i, -95.4200045428049+0i, -94.2845517186135+0i, 93.6287479850051+0i, -83.7083948970612+39.7221174209657i, -83.7083948970612-39.7221174209657i, -89.7405335285911+14.6972603541884i, -89.7405335285911-14.6972603541884i, -90.4677652619726+0i, 80.9227484547009+0i, -79.2808369338756+0i, -67.7641499054793+34.4882180369511i, -67.7641499054793-34.4882180369511i, -74.7131802385517+0i, -72.7892236613541+0i, -70.8748882290923+0i, -65.326216345093+24.6325729497989i, -65.326216345093-24.6325729497989i, -65.6613463045206+12.2012477360608i, -65.6613463045206-12.2012477360608i, -64.009437139127+0i, -53.8555784147338+28.3814233344012i, -53.8555784147338-28.3814233344012i, -60.372612826631+0i, -55.598407412763+0i, -53.8337490558365+13.1765372798343i, -53.8337490558365-13.1765372798343i, -48.7010835501729+24.5244827641945i, -48.7010835501729-24.5244827641945i, -51.620171425175+0i, -49.1047272072286+7.0804434036442i, -49.1047272072286-7.0804434036442i, -44.0755122578262+21.8965512206582i, -44.0755122578262-21.8965512206582i, -47.6686025497685+0i, -47.0350049752776+0i, 43.2054741656531+0i, -42.0546965543942+0i, -41.4311176038551+0i, -36.4574226401686+16.1634950480082i, -36.4574226401686-16.1634950480082i, -39.2901755793811+0i, -36.5376333751307+11.2152902727145i, -36.5376333751307-11.2152902727145i, -38.0398197891428+0i, -32.9946255929378+12.9867445602001i, -32.9946255929378-12.9867445602001i, -34.7321001383969+0i, -32.0667502593492+12.342590095597i, -32.0667502593492-12.342590095597i, -27.2830437098322+11.6992356475951i, -27.2830437098322-11.6992356475951i, -29.1247671355682+2.0847233845627i, -29.1247671355682-2.0847233845627i, -28.1216021055426+0i, -27.0745572919711+0i, 26.1565478253913+0i, -23.4210302095847+1.8723763695687i, -23.4210302095847-1.8723763695687i, 20.782836979896+0i, 16.5058357149619+0i, -15.9316203363047+0i, 13.2377600042936+0i, -11.9119569568831+0i, -11.1832867499603+0i, 8.99100195370794+0i, 7.62805946796798+0i, -7.44159556589097+0i, -6.46699019595805+0i, 5.57838460483725+0i, 5.07382264677001+0i, -4.77172378340461+0i, 4.21976444063592+0i, -2.86123099075901+0i, -2.69814683135512+0i, -2.29820560404041+0i, 2.05951624519943+0i, -1.8306332549612+0i, 1.66021670517454+0i, 1.03505989993491+0i, -0.773887754953459+0i, -0.416100454072758+0i, 0.213086170361661+0i, -3.42336062193255e-06+0i, 3.42336057523814e-06+0i), vectors = NULL);list(argv[[1]],argv[[2]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_listfiles.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_listfiles.java index 7058a42604c4499aa234492fedd22d77a83361e3..6b11db7b2dfe50eb3a22d6501181fb51f19067d6 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_listfiles.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_listfiles.java @@ -30,7 +30,8 @@ public class TestBuiltin_listfiles extends TestBase { @Test public void testlistfiles3() { // FastR bug; not recursing in to "." - assertEval("argv <- list('.', '^CITATION.*', FALSE, FALSE, TRUE, FALSE, FALSE, FALSE); .Internal(list.files(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]]))"); + assertEval(Ignored.Unknown, + "argv <- list('.', '^CITATION.*', FALSE, FALSE, TRUE, FALSE, FALSE, FALSE); .Internal(list.files(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]]))"); } @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 new file mode 100644 index 0000000000000000000000000000000000000000..725d9b47df88cb9f3c774ae1ffa574e8ca2a0934 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lockEnvironment.java @@ -0,0 +1,42 @@ +/* + * 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.test.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +// Checkstyle: stop line length check +public class TestBuiltin_lockEnvironment extends TestBase { + + @Test + public void testlockEnvironment() { + assertEval("lockEnvironment('foo', TRUE)"); + 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, 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 2af194603eb345275555dbab3cdeb0a747874f5e..1cb8f1375ebfd0fb2fa850c12c7d84df6fe0584c 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 @@ -31,5 +31,7 @@ public class TestBuiltin_log extends TestBase { assertEval("{ round( log(10,), digits = 5 ) }"); assertEval("{ round( log(10,2), digits = 5 ) }"); assertEval("{ round( log(10,10), digits = 5 ) }"); + assertEval("{ log(c(2,3), NA) } "); + assertEval("{ log(c(2,3), 0/0) } "); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInteropEval.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ls.java similarity index 63% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInteropEval.java rename to com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ls.java index f866e6f2e6f40e52d0b39934bb32c6aeef5dc77e..507802bf6a87ac883a7c9a3385e3f53962a02b57 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInteropEval.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ls.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -20,20 +20,22 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.test.library.fastr; + +package com.oracle.truffle.r.test.builtins; import org.junit.Test; import com.oracle.truffle.r.test.TestBase; -public class TestInteropEval extends TestBase { +public class TestBuiltin_ls extends TestBase { + @Test + public void basicTests() { + assertEval("f <- function(){ x <- 42; a <- 'two'; ls() }; f()"); + assertEval(template("e <- new.env(); assign('.x',42,e); assign('y','42',e); ls(envir=e, all.names=%0)", new String[]{"TRUE", "FALSE"})); + } @Test - public void testInteropEval() { - assertEvalFastR(".fastr.interop.eval('application/x-r', '14 + 2')", "16"); - assertEvalFastR(".fastr.interop.eval('application/x-r', '1')", "1"); - assertEvalFastR(".fastr.interop.eval('application/x-r', '1L')", "1L"); - assertEvalFastR(".fastr.interop.eval('application/x-r', 'TRUE')", "TRUE"); - assertEvalFastR(".fastr.interop.eval('application/x-r', 'as.character(123)')", "as.character(123)"); + public void invalidArgTests() { + assertEval(".Internal(ls(42, TRUE, TRUE))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_makenames.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_makenames.java index 4bdd7f1b7c7e4688d198e0316b0c262f72784f23..fcfe5c698cd975916cc3edeff9cbd57e06e5e152 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_makenames.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_makenames.java @@ -89,8 +89,10 @@ public class TestBuiltin_makenames extends TestBase { assertEval("{ make.names(\"else\")}"); assertEval("{ make.names(\"NA_integer_\", allow_=FALSE) }"); - assertEval(Output.IgnoreErrorContext, "{ make.names(\"a_a\", allow_=\"a\") }"); - assertEval(Output.IgnoreErrorContext, "{ make.names(\"a_a\", allow_=logical()) }"); - assertEval(Output.IgnoreErrorContext, "{ make.names(\"a_a\", allow_=NULL) }"); + assertEval("{ make.names(\"a_a\", allow_=\"a\") }"); + assertEval("{ make.names(\"a_a\", allow_=logical()) }"); + assertEval("{ make.names(\"a_a\", allow_=NULL) }"); + + assertEval("{ .Internal(make.names(42, F)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_makeunique.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_makeunique.java index b6a376df3dfde96adc008401d739792c529e4d09..db726d9db92d7e40ed5f7b2dce447fbd9a5ff9d8 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_makeunique.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_makeunique.java @@ -44,8 +44,16 @@ public class TestBuiltin_makeunique extends TestBase { assertEval("{ make.unique(c(\"a\", \"a\")) }"); assertEval("{ make.unique(c(\"a\", \"a\", \"a\")) }"); assertEval("{ make.unique(c(\"a\", \"a\"), \"_\") }"); - assertEval(Output.IgnoreErrorContext, "{ make.unique(1) }"); - assertEval(Output.IgnoreErrorContext, "{ make.unique(\"a\", 1) }"); - assertEval(Output.IgnoreErrorContext, "{ make.unique(\"a\", character()) }"); + assertEval("{ make.unique(1) }"); + assertEval("{ make.unique(\"a\", 1) }"); + assertEval("{ make.unique(\"a\", character()) }"); + + assertEval("{ .Internal(make.unique(c(7, 42), \".\")) }"); + assertEval("{ .Internal(make.unique(NULL, \".\")) }"); + assertEval("{ .Internal(make.unique(c(\"7\", \"42\"), 42)) }"); + assertEval("{ .Internal(make.unique(c(\"7\", \"42\"), character())) }"); + assertEval("{ .Internal(make.unique(c(\"7\", \"42\"), c(\".\", \".\"))) }"); + assertEval("{ .Internal(make.unique(c(\"7\", \"42\"), NULL)) }"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_match.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_match.java index bec7d0d686336e616d9e6e5afec822df165d07b2..564fb5e682e7e9d225d2fdf253e8f1f3ffba68a3 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_match.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_match.java @@ -200,9 +200,9 @@ public class TestBuiltin_match extends TestBase { assertEval("{ match(factor(c(\"a\", \"b\", \"a\")), \"a\") }"); assertEval("{ match(42, NULL) }"); - assertEval("{ match(c(7, 42), NULL }"); - assertEval("{ match(c(7, 42), NULL, integer() }"); - assertEval("{ match(c(7, 42), NULL, 1L }"); + assertEval("{ match(c(7, 42), NULL) }"); + assertEval(Ignored.ImplementationError, "{ match(c(7, 42), NULL, integer()) }"); + assertEval("{ match(c(7, 42), NULL, 1L) }"); assertEval("{ match(NULL, NULL) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matrix.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matrix.java index 9fcc5547d1cd6a1ca5b5d172561ab67b6baaf28c..e6957f67d0fc32a920ca0c1b248a1e05cde65ba9 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matrix.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matrix.java @@ -134,8 +134,7 @@ public class TestBuiltin_matrix extends TestBase { @Test public void testmatrix24() { - assertEval(Ignored.Unknown, - "argv <- list(c(TRUE, FALSE, FALSE, TRUE), 2L, 2L, TRUE, NULL, FALSE, FALSE); .Internal(matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); + assertEval("argv <- list(c(TRUE, FALSE, FALSE, TRUE), 2L, 2L, TRUE, NULL, FALSE, FALSE); .Internal(matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); } @Test @@ -180,8 +179,7 @@ public class TestBuiltin_matrix extends TestBase { @Test public void testmatrix33() { - assertEval(Ignored.Unknown, - "argv <- list(c(1+2i, 3-4i, 5+0i, -6+0i), 2L, 2L, TRUE, NULL, FALSE, FALSE); .Internal(matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); + assertEval("argv <- list(c(1+2i, 3-4i, 5+0i, -6+0i), 2L, 2L, TRUE, NULL, FALSE, FALSE); .Internal(matrix(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_max.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java index d1cd0ce9a3569fdcf8371d1fc99ab2384df9dd78..c2389ce4841980d8c774e2251f32ce9cc25b1a74 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 @@ -24,7 +24,7 @@ public class TestBuiltin_max extends TestBase { @Test public void testmax2() { - assertEval("argv <- list(structure(c(1208822400, 1209168000, 1208822400, 1209168000), class = c('POSIXct', 'POSIXt')), na.rm = TRUE);max(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(1208822400, 1209168000, 1208822400, 1209168000), class = c('POSIXct', 'POSIXt')));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE);"); } @Test @@ -59,8 +59,7 @@ public class TestBuiltin_max extends TestBase { @Test public void testmax9() { - assertEval(Output.IgnoreErrorContext, - "argv <- list(structure(list(x = c(-1, 1, 1, -1, -1, 1, 1, -1), y = c(-0.701149425287356, -0.701149425287356, -0.701149425287356, -0.701149425287356, 0.701149425287356, 0.701149425287356, 0.701149425287356, 0.701149425287356), z = c(-0.4, -0.4, 0.4, 0.4, -0.4, -0.4, 0.4, 0.4)), .Names = c('x', 'y', 'z'), row.names = c(NA, -8L), class = 'data.frame'), na.rm = FALSE);max(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(list(x = c(-1, 1, 1, -1, -1, 1, 1, -1), y = c(-0.701149425287356, -0.701149425287356, -0.701149425287356, -0.701149425287356, 0.701149425287356, 0.701149425287356, 0.701149425287356, 0.701149425287356), z = c(-0.4, -0.4, 0.4, 0.4, -0.4, -0.4, 0.4, 0.4)), .Names = c('x', 'y', 'z'), row.names = c(NA, -8L), class = 'data.frame'));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test @@ -95,32 +94,32 @@ public class TestBuiltin_max extends TestBase { @Test public void testmax16() { - assertEval("argv <- list(structure(c(11368.8306749654, 11347.7238090355, 11341.9182102121, 11392.4878842821, 11367.3445285107, 11337.9245694652, 11332.0560643654, 11356.4682624019, 11387.6852128883, 11364.9132677, 11391.3319486445, 11374.2254758319, 11347.9708838458, 11353.2031583386, 11333.3748092474, 11323.9154302836, 11373.0896246266, 11330.2228965024, 11354.2399044028, 11367.8070731596, 11392.4287034031, 11357.6915504499, 11356.9044667059, 11335.1409634408, 11375.8374661156, 11354.7726842454, 11358.781884864, 11337.5281579299, 11339.0060699913, 11364.6998397419, 11363.2410538797, 11328.3945066198, 11325.487840571, 11367.9956844538, 11388.0030639744, 11364.8664695648, 11362.2630523606, 11359.821940674, 11391.9566656714, 11358.5349275633, 11370.7951655071, 11365.1078852355, 11339.7208074429, 11341.0716148671, 11374.0516736354, 11354.6799581982, 11335.2588737891, 11375.2688788734, 11330.349134828, 11383.518146432, 11366.0251480173, 11362.0011677193, 11346.0144123337, 11354.7192011815, 11358.0308680837, 11335.6606452791, 11360.0741421962, 11328.2693021996, 11342.4429152855, 11337.8889663466, 11342.9353336683, 11385.6565872063, 11354.2364726327, 11377.5989422849, 11384.6433324409, 11351.9186946652, 11327.4665936357, 11346.4841244179, 11373.6608162634, 11346.6330733448, 11367.1289885738, 11381.8430187805, 11382.9292165297, 11350.3951496719, 11349.6345719923, 11385.6811798196, 11368.1021034038, 11374.8755054101, 11365.3712412571, 11386.2157128048, 11343.5611108569, 11336.3882076922, 11385.0515660313, 11358.2337640012, 11384.3940280117, 11336.2435535709, 11376.0672136671, 11373.7149224868, 11389.0607372806, 11361.3352610911, 11372.8220707406, 11350.2233569878, 11330.0611188328, 11387.9111462012, 11342.8262750218, 11364.340121117, 11330.7252423461, 11381.8354922482, 11345.257457911, 11377.7995935893), class = 'Date'), na.rm = TRUE);max(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(11368.8306749654, 11347.7238090355, 11341.9182102121, 11392.4878842821, 11367.3445285107, 11337.9245694652, 11332.0560643654, 11356.4682624019, 11387.6852128883, 11364.9132677, 11391.3319486445, 11374.2254758319, 11347.9708838458, 11353.2031583386, 11333.3748092474, 11323.9154302836, 11373.0896246266, 11330.2228965024, 11354.2399044028, 11367.8070731596, 11392.4287034031, 11357.6915504499, 11356.9044667059, 11335.1409634408, 11375.8374661156, 11354.7726842454, 11358.781884864, 11337.5281579299, 11339.0060699913, 11364.6998397419, 11363.2410538797, 11328.3945066198, 11325.487840571, 11367.9956844538, 11388.0030639744, 11364.8664695648, 11362.2630523606, 11359.821940674, 11391.9566656714, 11358.5349275633, 11370.7951655071, 11365.1078852355, 11339.7208074429, 11341.0716148671, 11374.0516736354, 11354.6799581982, 11335.2588737891, 11375.2688788734, 11330.349134828, 11383.518146432, 11366.0251480173, 11362.0011677193, 11346.0144123337, 11354.7192011815, 11358.0308680837, 11335.6606452791, 11360.0741421962, 11328.2693021996, 11342.4429152855, 11337.8889663466, 11342.9353336683, 11385.6565872063, 11354.2364726327, 11377.5989422849, 11384.6433324409, 11351.9186946652, 11327.4665936357, 11346.4841244179, 11373.6608162634, 11346.6330733448, 11367.1289885738, 11381.8430187805, 11382.9292165297, 11350.3951496719, 11349.6345719923, 11385.6811798196, 11368.1021034038, 11374.8755054101, 11365.3712412571, 11386.2157128048, 11343.5611108569, 11336.3882076922, 11385.0515660313, 11358.2337640012, 11384.3940280117, 11336.2435535709, 11376.0672136671, 11373.7149224868, 11389.0607372806, 11361.3352610911, 11372.8220707406, 11350.2233569878, 11330.0611188328, 11387.9111462012, 11342.8262750218, 11364.340121117, 11330.7252423461, 11381.8354922482, 11345.257457911, 11377.7995935893), class = 'Date'));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE);"); } @Test public void testmax17() { - assertEval(Output.IgnoreErrorContext, "argv <- list(structure(c(3L, 2L, 1L), .Label = c('A', 'B', 'C'), class = c('ordered', 'factor')), na.rm = FALSE);max(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(3L, 2L, 1L), .Label = c('A', 'B', 'C'), class = c('ordered', 'factor')));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testmax18() { - assertEval("argv <- list(structure(c(1338544800L, 1338566400L, 1338588000L, 1338609600L, 1338631200L, 1338652800L, 1338674400L, 1338696000L, 1338717600L, 1338739200L, 1338760800L, 1338782400L, 1338804000L, 1338825600L, 1338847200L, 1338868800L, 1338890400L, 1338912000L, 1338933600L, 1338955200L, 1338976800L, 1338998400L, 1339020000L, 1339041600L), class = c('POSIXct', 'POSIXt'), tzone = ''), na.rm = TRUE);max(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(1338544800L, 1338566400L, 1338588000L, 1338609600L, 1338631200L, 1338652800L, 1338674400L, 1338696000L, 1338717600L, 1338739200L, 1338760800L, 1338782400L, 1338804000L, 1338825600L, 1338847200L, 1338868800L, 1338890400L, 1338912000L, 1338933600L, 1338955200L, 1338976800L, 1338998400L, 1339020000L, 1339041600L), class = c('POSIXct', 'POSIXt'), tzone = ''));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE);"); } @Test public void testmax19() { - assertEval("argv <- list(structure(list(c(1L, 2L, 4L), 1:3, c(2L, 1L)), class = c('package_version', 'numeric_version')), na.rm = FALSE);max(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(list(c(1L, 2L, 4L), 1:3, c(2L, 1L)), class = c('package_version', 'numeric_version')));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testmax20() { - assertEval("argv <- list(structure(c(1208822400, 1209168000), class = c('POSIXct', 'POSIXt'), tzone = 'GMT'), na.rm = FALSE);max(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(1208822400, 1209168000), class = c('POSIXct', 'POSIXt'), tzone = 'GMT'));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testmax21() { - assertEval("argv <- list(structure(c(13823, NA), class = 'Date'), na.rm = TRUE);max(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(13823, NA), class = 'Date'));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE);"); } @Test @@ -217,7 +216,7 @@ public class TestBuiltin_max extends TestBase { assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(integer(0)) }"); assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(integer()) }"); - assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(as.double(NA), na.rm=TRUE) }"); + assertEval(Output.IgnoreWarningContext, "{ 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) }"); } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_merge.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_merge.java index 8663c21840ec2756e5429aafa089fe849a5853d2..4674eef29d533a1422cb0ef50bde98cc40d08a81 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_merge.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_merge.java @@ -37,4 +37,13 @@ public class TestBuiltin_merge extends TestBase { assertEval("argv <- structure(list(x = structure(list(gender = structure(c(1L, 1L, 2L), .Label = c('F', 'M'), class = 'factor'), age = c(20, 30, 40), filename = structure(1:3, .Label = c('q1.csv', 'q2.csv', 'q3.csv'), class = 'factor')), .Names = c('gender', 'age', 'filename'), row.names = c(NA, -3L), class = 'data.frame'), y = structure(list(effsize = c(3.5, 2, 1.7), constraint = c(0.40625, 0.5, 0.882), outdegree = c(4, 2, 2), indegree = c(4, 2, 3), efficiency = c(0.625, 0.5, 0.444444444444444), hierarchy = c(0, 0, 0.333333333333333), centralization = c(0.833333333333333, 1, 0.333333333333333), gden = c(0.5, 0.666666666666667, 0.666666666666667), ego.gden = c(0.166666666666667, 0, 0.5), filename = structure(1:3, .Label = c('q1.csv', 'q2.csv', 'q3.csv'), class = 'factor')), .Names = c('effsize', 'constraint', 'outdegree', 'indegree', 'efficiency', 'hierarchy', 'centralization', 'gden', 'ego.gden', 'filename'), row.names = c('q1.csv', 'q2.csv', 'q3.csv'), class = 'data.frame'), by = 'filename'), .Names = c('x', 'y', 'by'));" + "do.call('merge', argv)"); } + + @Test + public void testExamplesFromHelp() { + String init = "x <- data.frame(k1 = c(NA,NA,3,4,5), k2 = c(1,NA,NA,4,5), data = 1:5);" + + "y <- data.frame(k1 = c(NA,2,NA,4,5), k2 = c(NA,NA,3,4,5), data = 1:5);"; + assertEval(init + "merge(x, y, by = c('k1','k2'))"); + assertEval(init + "merge(x, y, by = 'k1')"); + assertEval(Ignored.ImplementationError, init + "merge(x, y, by = 'k2', incomparables = NA)"); + } } 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 55338bf8ec5205bbbf23fbd45af1ac3713b12613..beca4afa68c9c66c08c810f15394cc894ace305c 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 @@ -39,12 +39,12 @@ public class TestBuiltin_min extends TestBase { @Test public void testmin5() { - assertEval("argv <- list(structure(list(c(1L, 2L, 4L), 1:3, c(2L, 1L)), class = c('package_version', 'numeric_version')), na.rm = FALSE);min(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(list(c(1L, 2L, 4L), 1:3, c(2L, 1L)), class = c('package_version', 'numeric_version')));min(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testmin6() { - assertEval("argv <- list(structure(c(1338544800L, 1338566400L, 1338588000L, 1338609600L, 1338631200L, 1338652800L, 1338674400L, 1338696000L, 1338717600L, 1338739200L, 1338760800L, 1338782400L, 1338804000L, 1338825600L, 1338847200L, 1338868800L, 1338890400L, 1338912000L, 1338933600L, 1338955200L, 1338976800L, 1338998400L, 1339020000L, 1339041600L), class = c('POSIXct', 'POSIXt'), tzone = ''), na.rm = TRUE);min(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(1338544800L, 1338566400L, 1338588000L, 1338609600L, 1338631200L, 1338652800L, 1338674400L, 1338696000L, 1338717600L, 1338739200L, 1338760800L, 1338782400L, 1338804000L, 1338825600L, 1338847200L, 1338868800L, 1338890400L, 1338912000L, 1338933600L, 1338955200L, 1338976800L, 1338998400L, 1339020000L, 1339041600L), class = c('POSIXct', 'POSIXt'), tzone = ''));min(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE);"); } @Test @@ -54,12 +54,12 @@ public class TestBuiltin_min extends TestBase { @Test public void testmin8() { - assertEval(Output.IgnoreErrorContext, "argv <- list(structure(c(3L, 2L, 1L), .Label = c('A', 'B', 'C'), class = c('ordered', 'factor')), na.rm = FALSE);min(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(3L, 2L, 1L), .Label = c('A', 'B', 'C'), class = c('ordered', 'factor')));min(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testmin9() { - assertEval("argv <- list(structure(c(11368.8306749654, 11347.7238090355, 11341.9182102121, 11392.4878842821, 11367.3445285107, 11337.9245694652, 11332.0560643654, 11356.4682624019, 11387.6852128883, 11364.9132677, 11391.3319486445, 11374.2254758319, 11347.9708838458, 11353.2031583386, 11333.3748092474, 11323.9154302836, 11373.0896246266, 11330.2228965024, 11354.2399044028, 11367.8070731596, 11392.4287034031, 11357.6915504499, 11356.9044667059, 11335.1409634408, 11375.8374661156, 11354.7726842454, 11358.781884864, 11337.5281579299, 11339.0060699913, 11364.6998397419, 11363.2410538797, 11328.3945066198, 11325.487840571, 11367.9956844538, 11388.0030639744, 11364.8664695648, 11362.2630523606, 11359.821940674, 11391.9566656714, 11358.5349275633, 11370.7951655071, 11365.1078852355, 11339.7208074429, 11341.0716148671, 11374.0516736354, 11354.6799581982, 11335.2588737891, 11375.2688788734, 11330.349134828, 11383.518146432, 11366.0251480173, 11362.0011677193, 11346.0144123337, 11354.7192011815, 11358.0308680837, 11335.6606452791, 11360.0741421962, 11328.2693021996, 11342.4429152855, 11337.8889663466, 11342.9353336683, 11385.6565872063, 11354.2364726327, 11377.5989422849, 11384.6433324409, 11351.9186946652, 11327.4665936357, 11346.4841244179, 11373.6608162634, 11346.6330733448, 11367.1289885738, 11381.8430187805, 11382.9292165297, 11350.3951496719, 11349.6345719923, 11385.6811798196, 11368.1021034038, 11374.8755054101, 11365.3712412571, 11386.2157128048, 11343.5611108569, 11336.3882076922, 11385.0515660313, 11358.2337640012, 11384.3940280117, 11336.2435535709, 11376.0672136671, 11373.7149224868, 11389.0607372806, 11361.3352610911, 11372.8220707406, 11350.2233569878, 11330.0611188328, 11387.9111462012, 11342.8262750218, 11364.340121117, 11330.7252423461, 11381.8354922482, 11345.257457911, 11377.7995935893), class = 'Date'), na.rm = TRUE);min(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(11368.8306749654, 11347.7238090355, 11341.9182102121, 11392.4878842821, 11367.3445285107, 11337.9245694652, 11332.0560643654, 11356.4682624019, 11387.6852128883, 11364.9132677, 11391.3319486445, 11374.2254758319, 11347.9708838458, 11353.2031583386, 11333.3748092474, 11323.9154302836, 11373.0896246266, 11330.2228965024, 11354.2399044028, 11367.8070731596, 11392.4287034031, 11357.6915504499, 11356.9044667059, 11335.1409634408, 11375.8374661156, 11354.7726842454, 11358.781884864, 11337.5281579299, 11339.0060699913, 11364.6998397419, 11363.2410538797, 11328.3945066198, 11325.487840571, 11367.9956844538, 11388.0030639744, 11364.8664695648, 11362.2630523606, 11359.821940674, 11391.9566656714, 11358.5349275633, 11370.7951655071, 11365.1078852355, 11339.7208074429, 11341.0716148671, 11374.0516736354, 11354.6799581982, 11335.2588737891, 11375.2688788734, 11330.349134828, 11383.518146432, 11366.0251480173, 11362.0011677193, 11346.0144123337, 11354.7192011815, 11358.0308680837, 11335.6606452791, 11360.0741421962, 11328.2693021996, 11342.4429152855, 11337.8889663466, 11342.9353336683, 11385.6565872063, 11354.2364726327, 11377.5989422849, 11384.6433324409, 11351.9186946652, 11327.4665936357, 11346.4841244179, 11373.6608162634, 11346.6330733448, 11367.1289885738, 11381.8430187805, 11382.9292165297, 11350.3951496719, 11349.6345719923, 11385.6811798196, 11368.1021034038, 11374.8755054101, 11365.3712412571, 11386.2157128048, 11343.5611108569, 11336.3882076922, 11385.0515660313, 11358.2337640012, 11384.3940280117, 11336.2435535709, 11376.0672136671, 11373.7149224868, 11389.0607372806, 11361.3352610911, 11372.8220707406, 11350.2233569878, 11330.0611188328, 11387.9111462012, 11342.8262750218, 11364.340121117, 11330.7252423461, 11381.8354922482, 11345.257457911, 11377.7995935893), class = 'Date'));min(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE);"); } @Test @@ -84,12 +84,12 @@ public class TestBuiltin_min extends TestBase { @Test public void testmin14() { - assertEval("argv <- list(structure(c(13823, NA), class = 'Date'), na.rm = TRUE);min(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(13823, NA), class = 'Date'));min(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE);"); } @Test public void testmin15() { - assertEval("argv <- list(structure(c(1208822400, 1209168000), class = c('POSIXct', 'POSIXt'), tzone = 'GMT'), na.rm = FALSE);min(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(1208822400, 1209168000), class = c('POSIXct', 'POSIXt'), tzone = 'GMT'));min(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test @@ -175,7 +175,7 @@ public class TestBuiltin_min extends TestBase { assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ min(integer(0)) }"); assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ min(integer()) }"); - assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ min(as.double(NA), na.rm=TRUE) }"); + assertEval(Output.IgnoreWarningContext, "{ 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) }"); } 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 7a1ba027b7e2836032a9fc06232474901b940c51..cd568a219dfdb357ab3e656147f43c3f6ef9d095 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 @@ -203,6 +203,7 @@ public class TestBuiltin_names extends TestBase { assertEval("v <- parse(text=\"useDynLib(digest, digest_impl=digest)\"); names(v[[1]][[3]])"); assertEval("{ x<-c(1,2,3); dim(x)<-3; dimnames(x)<-list(c(11,12,13)); names(x) }"); assertEval("{ symNames <- c(\"foobar\", \"bar\"); names(symNames) = symNames; names(names(symNames)); }"); + assertEval("{ y<-c(d=\"e\"); attr(y, \"foo\")<-\"foo\"; x<-c(42); names(x)<-y; attributes(names(x)) }"); } @Test 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 9748eedf2febcaacff0efa32f501bb2adc432acb..eb57d88caea23c253cce644a916e49e6d435029f 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 @@ -82,7 +82,7 @@ public class TestBuiltin_nchar extends TestBase { assertEval("{ nchar(c(\"hello\", \"hi\")) }"); assertEval("{ nchar(c(\"hello\", \"hi\", 10, 130)) }"); assertEval("{ nchar(c(10,130)) }"); - assertEval("{ .Internal(nchar(c(10,130), 'chars', FALSE) }"); - assertEval("{ .Internal(nchar('ff', 'chars', FALSE) }"); + assertEval("{ .Internal(nchar(c(10,130), 'chars', FALSE)) }"); + assertEval("{ .Internal(nchar('ff', 'chars', FALSE)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_newenv.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_newenv.java new file mode 100644 index 0000000000000000000000000000000000000000..10e41b465384b0aadc8c76a53d8e9b15b0dcee5a --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_newenv.java @@ -0,0 +1,40 @@ +/* + * 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.test.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +// Checkstyle: stop line length check +public class TestBuiltin_newenv extends TestBase { + + @Test + public void testnewenv() { + assertEval(Output.ContainsReferences, "new.env()"); + assertEval(Output.ContainsReferences, "new.env(1,,2)"); + assertEval(Output.ContainsReferences, "new.env(logical(),new.env(),1000)"); + assertEval(Output.ContainsReferences, "parent.env(new.env())"); + assertEval(Output.ContainsReferences, "e <- new.env(); e; parent.env(new.env(TRUE, e))"); + } +} 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 829f43019c2d1f91e4349d75ae0a68f00fefac67..c43232942555d24f347259f323d689e0fd7ed778 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 @@ -59,8 +59,7 @@ public class TestBuiltin_nzchar extends TestBase { @Test public void testnzchar9() { - assertEval(Ignored.Unknown, - "argv <- list(c(' \\036 The other major change was an error for asymmetric loss matrices,', ' prompted by a user query. With L=loss asymmetric, the altered', ' priors were computed incorrectly - they were using L' instead of L.', ' Upshot - the tree would not not necessarily choose optimal splits', ' for the given loss matrix. Once chosen, splits were evaluated', ' correctly. The printed “improvement” values are of course the', ' wrong ones as well. It is interesting that for my little test', ' case, with L quite asymmetric, the early splits in the tree are', ' unchanged - a good split still looks good.'));nzchar(argv[[1]]);"); + assertEval("argv <- list(c(' \\036 The other major change was an error for asymmetric loss matrices,', ' prompted by a user query. With L=loss asymmetric, the altered', ' priors were computed incorrectly - they were using L\\' instead of L.', ' Upshot - the tree would not not necessarily choose optimal splits', ' for the given loss matrix. Once chosen, splits were evaluated', ' correctly. The printed “improvement” values are of course the', ' wrong ones as well. It is interesting that for my little test', ' case, with L quite asymmetric, the early splits in the tree are', ' unchanged - a good split still looks good.'));nzchar(argv[[1]]);"); } @Test @@ -72,4 +71,16 @@ public class TestBuiltin_nzchar extends TestBase { public void testnzchar12() { assertEval("argv <- list('');do.call('nzchar', argv)"); } + + @Test + public void keepNATests() { + assertEval("nzchar(c('asdasd', NA), keepNA=TRUE)"); + assertEval("nzchar(c('asdasd', NA), keepNA=FALSE)"); + } + + @Test + public void nonStringArgs() { + assertEval("nzchar(list('x', 42, list('a'), list()))"); + assertEval("nzchar(NULL)"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_oldClass.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_oldClass.java index 277eb8a0336169f0df32aae62a5de70202af22ce..40856bd5f63e68505c36d882db89045a0c774f96 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_oldClass.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_oldClass.java @@ -126,5 +126,6 @@ public class TestBuiltin_oldClass extends TestBase { public void testGetClass() { assertEval("{ x<-1; oldClass(x) }"); assertEval("{ oldClass(NULL) }"); + assertEval("{ f <- quote(foo(42)); class(f)<-'myclass'; oldClass(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 3f34620f9e2e627694684588e82f94439904bce0..f201c9e1243b2b5b93c6bad34f57413578e5b1ce 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 @@ -95,7 +95,7 @@ public class TestBuiltin_operators extends TestBase { @Test public void testoperators16() { - assertEval(Ignored.Unknown, "argv <- list(1.678932e-305, 0+0i);`+`(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(1.678932e-305, 0+0i);`+`(argv[[1]],argv[[2]]);"); } @Test @@ -146,8 +146,7 @@ public class TestBuiltin_operators extends TestBase { @Test public void testoperators26() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(1+1i, 2+2i, 1.2+10i, 2.4+20i), .Dim = c(2L, 2L), .Dimnames = list(c('x', ''), c('a', 'b'))), 3.14159265358979);`+`(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(1+1i, 2+2i, 1.2+10i, 2.4+20i), .Dim = c(2L, 2L), .Dimnames = list(c('x', ''), c('a', 'b'))), 3.14159265358979);`+`(argv[[1]],argv[[2]]);"); } @Test @@ -167,8 +166,7 @@ public class TestBuiltin_operators extends TestBase { @Test public void testoperators30() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(-0.560475646552213+0i, 0.7424437487+0i, 1.39139505579429+0i, 0.928710764113827+0i, -0.469267985412949+0i, 0.7424437487+0i, 0.460916205989202+0i, -0.452623703774585+0i, -0.0945011868321433+0i, -0.331818442379127+0i, 1.39139505579429+0i, -0.452623703774585+0i, 0.400771450594052+0i, -0.927967220342259+0i, -0.790922791530657+0i, 0.928710764113827+0i, -0.0945011868321433+0i, -0.927967220342259+0i, 0.701355901563686+0i, -0.600841318509537+0i, -0.469267985412949+0i, -0.331818442379127+0i, -0.790922791530657+0i, -0.600841318509537+0i, -0.625039267849257+0i), .Dim = c(5L, 5L)), c(0-1.68669331074241i, 0+0.837787044494525i, 0+0.153373117836515i, 0-1.13813693701195i, 0+1.25381492106993i, 0+0.426464221476814i, 0-0.295071482992271i, 0+0.895125661045022i, 0+0.878133487533042i, 0+0.821581081637487i, 0+0.688640254100091i, 0+0.553917653537589i, 0-0.0619117105767217i, 0-0.305962663739917i, 0-0.380471001012383i, 0-0.694706978920513i, 0-0.207917278019599i, 0-1.26539635156826i, 0+2.16895596533851i, 0+1.20796199830499i, 0-1.12310858320335i, 0-0.402884835299076i, 0-0.466655353623219i, 0+0.779965118336318i, 0-0.0833690664718293i));`+`(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(-0.560475646552213+0i, 0.7424437487+0i, 1.39139505579429+0i, 0.928710764113827+0i, -0.469267985412949+0i, 0.7424437487+0i, 0.460916205989202+0i, -0.452623703774585+0i, -0.0945011868321433+0i, -0.331818442379127+0i, 1.39139505579429+0i, -0.452623703774585+0i, 0.400771450594052+0i, -0.927967220342259+0i, -0.790922791530657+0i, 0.928710764113827+0i, -0.0945011868321433+0i, -0.927967220342259+0i, 0.701355901563686+0i, -0.600841318509537+0i, -0.469267985412949+0i, -0.331818442379127+0i, -0.790922791530657+0i, -0.600841318509537+0i, -0.625039267849257+0i), .Dim = c(5L, 5L)), c(0-1.68669331074241i, 0+0.837787044494525i, 0+0.153373117836515i, 0-1.13813693701195i, 0+1.25381492106993i, 0+0.426464221476814i, 0-0.295071482992271i, 0+0.895125661045022i, 0+0.878133487533042i, 0+0.821581081637487i, 0+0.688640254100091i, 0+0.553917653537589i, 0-0.0619117105767217i, 0-0.305962663739917i, 0-0.380471001012383i, 0-0.694706978920513i, 0-0.207917278019599i, 0-1.26539635156826i, 0+2.16895596533851i, 0+1.20796199830499i, 0-1.12310858320335i, 0-0.402884835299076i, 0-0.466655353623219i, 0+0.779965118336318i, 0-0.0833690664718293i));`+`(argv[[1]],argv[[2]]);"); } @Test @@ -240,8 +238,7 @@ public class TestBuiltin_operators extends TestBase { @Test public void testoperators44() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(-0.560475646552213+0i, 0.7424437487+0i, 1.39139505579429+0i, 0.928710764113827+0i, -0.469267985412949+0i, 0.7424437487+0i, 0.460916205989202+0i, -0.452623703774585+0i, -0.0945011868321433+0i, -0.331818442379127+0i, 1.39139505579429+0i, -0.452623703774585+0i, 0.400771450594052+0i, -0.927967220342259+0i, -0.790922791530657+0i, 0.928710764113827+0i, -0.0945011868321433+0i, -0.927967220342259+0i, 0.701355901563686+0i, -0.600841318509537+0i, -0.469267985412949+0i, -0.331818442379127+0i, -0.790922791530657+0i, -0.600841318509537+0i, -0.625039267849257+0i), .Dim = c(5L, 5L)), structure(c(-0.560475646552213+0i, 0.742443748700001+0i, 1.39139505579429+0i, 0.928710764113827+0i, -0.469267985412949+0i, 0.742443748700001+0i, 0.460916205989202+0i, -0.452623703774585+0i, -0.094501186832143+0i, -0.331818442379127+0i, 1.39139505579429+0i, -0.452623703774585+0i, 0.400771450594052+0i, -0.927967220342258+0i, -0.790922791530656+0i, 0.928710764113827+0i, -0.094501186832143+0i, -0.927967220342258+0i, 0.701355901563685+0i, -0.600841318509537+0i, -0.469267985412949+0i, -0.331818442379127+0i, -0.790922791530656+0i, -0.600841318509537+0i, -0.625039267849256+0i), .Dim = c(5L, 5L)));`-`(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(-0.560475646552213+0i, 0.7424437487+0i, 1.39139505579429+0i, 0.928710764113827+0i, -0.469267985412949+0i, 0.7424437487+0i, 0.460916205989202+0i, -0.452623703774585+0i, -0.0945011868321433+0i, -0.331818442379127+0i, 1.39139505579429+0i, -0.452623703774585+0i, 0.400771450594052+0i, -0.927967220342259+0i, -0.790922791530657+0i, 0.928710764113827+0i, -0.0945011868321433+0i, -0.927967220342259+0i, 0.701355901563686+0i, -0.600841318509537+0i, -0.469267985412949+0i, -0.331818442379127+0i, -0.790922791530657+0i, -0.600841318509537+0i, -0.625039267849257+0i), .Dim = c(5L, 5L)), structure(c(-0.560475646552213+0i, 0.742443748700001+0i, 1.39139505579429+0i, 0.928710764113827+0i, -0.469267985412949+0i, 0.742443748700001+0i, 0.460916205989202+0i, -0.452623703774585+0i, -0.094501186832143+0i, -0.331818442379127+0i, 1.39139505579429+0i, -0.452623703774585+0i, 0.400771450594052+0i, -0.927967220342258+0i, -0.790922791530656+0i, 0.928710764113827+0i, -0.094501186832143+0i, -0.927967220342258+0i, 0.701355901563685+0i, -0.600841318509537+0i, -0.469267985412949+0i, -0.331818442379127+0i, -0.790922791530656+0i, -0.600841318509537+0i, -0.625039267849256+0i), .Dim = c(5L, 5L)));`-`(argv[[1]],argv[[2]]);"); } @Test @@ -1621,8 +1618,7 @@ public class TestBuiltin_operators extends TestBase { @Test public void testoperators323() { - 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)), structure(c(0.63829956885596+0i, -0.190923866036828-0.209348060979014i, -0.478761262752136-0.086103851005322i, -0.365383456834977+0.041833555661111i, -0.222902888615007-0.301211043305794i, 0.537261763078809+0i, 0.305061935059249+0.040985454461732i, 0.320062315956695-0.375563080684186i, 0.339383913939873+0.23302799386284i, -0.286918674221019+0.348301421162371i, 0.428338589082996+0.09065231252407i, -0.107969030611945+0.281263066654197i, 0.001811723298003+0.250507832255811i, 0.144305664871353+0.232873855829054i, 0.761400139936914+0i, -0.050390571101999+0.329984002238884i, 0.120127927801654-0.008394623232215i, -0.521562263306688+0.262168616442556i, 0.691801039177503+0i, -0.206933988216912-0.109088169082914i, -0.014684754774299-0.0242358465049725i, 0.848358097780775+0i, -0.232315601522623+0.249797304698912i, -0.362004462885974+0.102815998405382i, 0.086977040883207+0.118037795588006i), .Dim = c(5L, 5L)));`%*%`(argv[[1]],argv[[2]]);"); + 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)), structure(c(0.63829956885596+0i, -0.190923866036828-0.209348060979014i, -0.478761262752136-0.086103851005322i, -0.365383456834977+0.041833555661111i, -0.222902888615007-0.301211043305794i, 0.537261763078809+0i, 0.305061935059249+0.040985454461732i, 0.320062315956695-0.375563080684186i, 0.339383913939873+0.23302799386284i, -0.286918674221019+0.348301421162371i, 0.428338589082996+0.09065231252407i, -0.107969030611945+0.281263066654197i, 0.001811723298003+0.250507832255811i, 0.144305664871353+0.232873855829054i, 0.761400139936914+0i, -0.050390571101999+0.329984002238884i, 0.120127927801654-0.008394623232215i, -0.521562263306688+0.262168616442556i, 0.691801039177503+0i, -0.206933988216912-0.109088169082914i, -0.014684754774299-0.0242358465049725i, 0.848358097780775+0i, -0.232315601522623+0.249797304698912i, -0.362004462885974+0.102815998405382i, 0.086977040883207+0.118037795588006i), .Dim = c(5L, 5L)));`%*%`(argv[[1]],argv[[2]]);"); } @Test @@ -1922,6 +1918,14 @@ public class TestBuiltin_operators extends TestBase { assertEval("data.frame(factor(c(1,2,1))) == data.frame(factor(c(1,2,2)))"); } + @Test + public void testNames() { + assertEval("data <- c(1,2,3,4); names(data) <- c('a','b','c','d'); " + + "data[c('a','b')] + data[c('c','d')]; data[c('a','b')] + data[c('c')]; data[c('a')] + data[c('c','d')]; data[c('a')] + data[c('c')]; " + + "data[c('a')] + 1; 1 + data[c('a')]; data[c('a')] + c(1,2); c(1,2) + data[c('a')]; " + + "data[c('a','b')] + 1; 1 + data[c('a','b')]; data[c('a','b')] + c(1,2); c(1,2) + data[c('a','b')]"); + } + @Test public void testOperators() { assertEval("{ `+`(1,2) }"); @@ -1959,8 +1963,8 @@ public class TestBuiltin_operators extends TestBase { assertEval("{ c(1+1i,2-2i,3+3i) %*% c(4-4i,5+5i,6-6i) }"); assertEval("{ matrix(c(1+1i,0-0i,4+4i),3) %*% matrix(c(3+3i,1-1i,2+2i,0-0i,1+1i,2-2i),1) }"); - assertEval(Ignored.Unknown, "{ matrix(c(3+3i,1-1i,2+2i,0-0i,1+1i,2-2i),2) %*% c(1+1i,0-0i,4+4i) }"); - assertEval(Ignored.Unknown, "{ c(1+1i,0-0i,4+4i) %*% matrix(c(3+3i,1-1i,2+2i,0-0i,1+1i,2-2i),3) }"); + assertEval("{ matrix(c(3+3i,1-1i,2+2i,0-0i,1+1i,2-2i),2) %*% c(1+1i,0-0i,4+4i) }"); + assertEval("{ c(1+1i,0-0i,4+4i) %*% matrix(c(3+3i,1-1i,2+2i,0-0i,1+1i,2-2i),3) }"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_options.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_options.java index 5ada3fbc4176768d9ad2dce3ba538e65ec1d3d72..9e6696ec52b12a5a9bc0da34f275434966ca848b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_options.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_options.java @@ -41,4 +41,11 @@ public class TestBuiltin_options extends TestBase { public void testoptions5() { assertEval(Ignored.Unknown, "argv <- list(NULL); .Internal(options(argv[[1]]))"); } + + @Test + public void testOptions() { + assertEval("{ getOption(NULL) }"); + assertEval("{ getOption(character()) }"); + assertEval("{ options(\"timeout\", \"width\") }"); + } } 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 2f844c98643a735990bb20ec79ebf7c2dc6a0d77..0ae5ec00e3e78270807e7a889fa46c07c60b6411 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 @@ -160,5 +160,7 @@ public class TestBuiltin_order extends TestBase { assertEval("{ order(c(-1480, -974, -1576, -970), c(\"a\", \"b\", \"c\", \"d\")) }"); 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'))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parentenv.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parentenv.java new file mode 100644 index 0000000000000000000000000000000000000000..285f0fa6c305a681287e97e9468249fd5a8427bb --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parentenv.java @@ -0,0 +1,39 @@ +/* + * 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.test.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestBuiltin_parentenv extends TestBase { + + @Test + public void testParentEnv() { + assertEval("parent.env()"); + assertEval("parent.env(NULL)"); + assertEval("parent.env(1)"); + assertEval("parent.env(c(1,2,3))"); + assertEval("e <- new.env(); parent.env(e)"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parentenvassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parentenvassign.java new file mode 100644 index 0000000000000000000000000000000000000000..5a4beabc42275506ec6e55528bfbaecd3b7f71fe --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parentenvassign.java @@ -0,0 +1,44 @@ +/* + * 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.test.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestBuiltin_parentenvassign extends TestBase { + + @Test + public void testParentEnv() { + assertEval("parent.env() <- new.env()"); + assertEval(Output.IgnoreErrorContext, "parent.env(NULL) <- new.env()"); + assertEval(Output.IgnoreErrorContext, "parent.env(1) <- new.env()"); + assertEval(Output.IgnoreErrorContext, "parent.env(c(1,2,3)) <- new.env()"); + assertEval("parent.env(emptyenv()) <- new.env()"); + assertEval(Output.IgnoreErrorContext, "e <- new.env(); parent.env(e) <- 44"); + assertEval(Output.IgnoreErrorContext, Output.IgnoreErrorMessage, "e <- new.env(); parent.env(e) <- NULL"); + assertEval("e <- new.env(); parent.env(e) <- emptyenv(); parent.env(e)"); + assertEval(Output.IgnoreErrorContext, "e <- new.env(); parent.env(e) <- c(1,2,3)"); + assertEval(Output.ContainsReferences, "e <- new.env(); e2 <- new.env(); parent.env(e) <- e2; parent.env(e)"); + } +} 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 214688f26e294f6826f495abc2e93984ac28d9b1..748403bf04222400b0c2d1518b2ae61633adff42 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 @@ -31,6 +31,7 @@ public class TestBuiltin_parse extends TestBase { @Test public void testParseVector() { assertEval("parse(text=deparse(c(1, 2, 3)))"); + assertEval("{ parse(text=c(\"for (i in 1:10) {\", \" x[i] <- i\", \"}\")) }"); } @Test @@ -51,4 +52,9 @@ public class TestBuiltin_parse extends TestBase { assertEval("parse(text='somethingthatdoesnotexist')"); assertEval(Ignored.ImplementationError, "attributes(parse(text='somethingthatdoesnotexist'))"); } + + @Test + public void testArgumentsCasts() { + assertEval(".Internal(parse(stdin(), c(1,2), c('expr1', 'expr2'), '?', '<weird-text', 'unknown'))"); + } } 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 a2a32c3e70587024cdb79118f7cdb9afc056e7f8..000d12c09fec9d6ff3992dda94035b761e426568 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 @@ -36,4 +36,10 @@ public class TestBuiltin_pathexpand extends TestBase { public void testpathexpand5() { assertEval("argv <- structure(list(path = '/tmp/RtmpagC9oa/Pkgs/exNSS4'), .Names = 'path');do.call('path.expand', argv)"); } + + @Test + public void testArgsValidation() { + assertEval(Output.IgnoreErrorContext, "path.expand(NULL)"); + assertEval(Output.IgnoreErrorContext, "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 04cbdaf00cffb90b3e034b69d385dab1f876a3b1..d88d8ba6957cb9c134ce6025dd02968fee4bfe6c 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 @@ -56,4 +56,13 @@ public class TestBuiltin_pmatch extends TestBase { public void testpmatch8() { assertEval("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]]))"); } + + @Test + public void testArgumentsCasts() { + assertEval("pmatch(NULL, 1)"); + assertEval("pmatch(1, NULL)"); + 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), duplicates.ok=42)"); + } } 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 373b799a388d2d4e069122a6c11571f143008413..28c1a51ff1840c44ee62e6e5d46db9ec687c66f3 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 @@ -101,4 +101,12 @@ public class TestBuiltin_pmin extends TestBase { assertEval(Output.IgnoreErrorContext, "{ pmin(as.raw(42)) }"); assertEval(Output.IgnoreErrorContext, "{ pmin(7+42i) }"); } + + @Test + public void testArgsCasting() { + assertEval("pmin(c(1,2), c(3,0), na.rm='asd')"); + assertEval("pmin(c(1,2), c(3,0), na.rm=NA)"); + assertEval("pmin(c(1,2), c(3,NA), na.rm=c(42, 0))"); + assertEval(".Internal(pmin(3, quote(a)))"); + } } 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 eb9267bcaa420e0c33a8d34afc524565e1592572..67ced8d5a6895c962b9285c87485d60b8a411db1 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 @@ -21,4 +21,9 @@ public class TestBuiltin_primUntrace extends TestBase { public void testprimUntrace1() { assertEval("argv <- list(.Primitive('sum'));.primUntrace(argv[[1]]);"); } + + @Test + public void testArgsCasts() { + assertEval(Output.IgnoreErrorContext, ".primUntrace(42)"); + } } 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 eb2f41390a276a78aff063abaf6e838aab057780..a4e57175ddfa4f8ff1d9b0ee8fb0332a803cec65 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 @@ -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(Ignored.Unknown, Output.IgnoreErrorContext, "{ x <- qr(cbind(1:10,2:11), LAPACK=TRUE) ; qr.coef(x, 1:2) }"); + assertEval(Output.IgnoreErrorContext, "{ 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_range.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_range.java index 5e2b8b7db4991e5d81d2e8c0a67adb13d7d7633e..d6c052886fb36efe6bbcae72d791115e4b12aacc 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_range.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_range.java @@ -19,119 +19,103 @@ public class TestBuiltin_range extends TestBase { @Test public void testrange1() { - assertEval("argv <- list(c(0.0303542455381287, 0.030376780241572, 0.030376780241572, 0.0317964665585001, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0334189652064179, 0.0352217414818821, 0.0354245538128718, 0.0354245538128718, 0.0376780241572021, 0.0376780241572021, 0.0376780241572021, 0.0376780241572021, 0.0406300703082748, 0.0406300703082748, 0.0406300703082748, 0.0440778799351001, 0.048021453037678, 0.0524607896160087, 0.0524607896160087, 0.0524607896160087, 0.0628267531999279, 0.0693167477915991, 0.0981611681990265, 0.134937804218497, 0.179646655850009, 0.437804218496485), na.rm = FALSE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(c(0.0303542455381287, 0.030376780241572, 0.030376780241572, 0.0317964665585001, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0334189652064179, 0.0352217414818821, 0.0354245538128718, 0.0354245538128718, 0.0376780241572021, 0.0376780241572021, 0.0376780241572021, 0.0376780241572021, 0.0406300703082748, 0.0406300703082748, 0.0406300703082748, 0.0440778799351001, 0.048021453037678, 0.0524607896160087, 0.0524607896160087, 0.0524607896160087, 0.0628267531999279, 0.0693167477915991, 0.0981611681990265, 0.134937804218497, 0.179646655850009, 0.437804218496485));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testrange2() { - assertEval("argv <- list(structure(c(52L, 52L), .Names = c('y', 'x')), na.rm = FALSE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(52L, 52L), .Names = c('y', 'x')));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testrange3() { - assertEval("argv <- list(c(-2.92498527625946, 2.46253591019012), na.rm = FALSE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(c(-2.92498527625946, 2.46253591019012));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testrange4() { - assertEval("argv <- list(c(1.4615016373309e+48, 5.70899077082384e+45, 2.23007451985306e+43, 8.71122859317602e+40, 3.40282366920938e+38, 1.32922799578492e+36, 5.19229685853483e+33, 2.02824096036517e+31, 7.92281625142643e+28, 3.09485009821345e+26, 1.20892581961463e+24, 4.72236648286965e+21, 18446744073709551616, 72057594037927936, 281474976710656, 1099511627776, 4294967296, 16777216, 65536, 256, 1, 0.00390625, 1.52587890625e-05, 5.96046447753906e-08, 2.3283064365387e-10, 9.09494701772928e-13, 3.5527136788005e-15, 1.38777878078145e-17, 5.42101086242752e-20, 2.11758236813575e-22, 8.27180612553028e-25), na.rm = FALSE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(c(1.4615016373309e+48, 5.70899077082384e+45, 2.23007451985306e+43, 8.71122859317602e+40, 3.40282366920938e+38, 1.32922799578492e+36, 5.19229685853483e+33, 2.02824096036517e+31, 7.92281625142643e+28, 3.09485009821345e+26, 1.20892581961463e+24, 4.72236648286965e+21, 18446744073709551616, 72057594037927936, 281474976710656, 1099511627776, 4294967296, 16777216, 65536, 256, 1, 0.00390625, 1.52587890625e-05, 5.96046447753906e-08, 2.3283064365387e-10, 9.09494701772928e-13, 3.5527136788005e-15, 1.38777878078145e-17, 5.42101086242752e-20, 2.11758236813575e-22, 8.27180612553028e-25));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testrange5() { - assertEval("argv <- list(1:3, finite = TRUE, na.rm = FALSE);range(argv[[1]],argv[[2]],argv[[3]]);"); + assertEval("argv <- list(1:3, finite = TRUE);range(argv[[1]][[1]],argv[[1]][[2]],argv[[1]][[3]], na.rm = FALSE);"); } @Test public void testrange6() { - assertEval("argv <- list(c(1L, 3L, 7L, 14L, 21L, 20L, 19L, 9L, 4L, 2L), 0, na.rm = FALSE);range(argv[[1]],argv[[2]],argv[[3]]);"); + assertEval("argv <- list(c(1L, 3L, 7L, 14L, 21L, 20L, 19L, 9L, 4L, 2L), 0);range(argv[[1]][[1]],argv[[1]][[2]],argv[[1]][[3]], na.rm = FALSE);"); } @Test public void testrange7() { - assertEval("argv <- list(c(8.2, 9.7, 12.25, 16.5, 21.5, 14.5, 20, 23.45, 25.8, 27.3, 22.4, 24.5, 25.95, 27.3, 30.9), numeric(0), NULL, na.rm = FALSE);range(argv[[1]],argv[[2]],argv[[3]],argv[[4]]);"); + assertEval("argv <- list(c(8.2, 9.7, 12.25, 16.5, 21.5, 14.5, 20, 23.45, 25.8, 27.3, 22.4, 24.5, 25.95, 27.3, 30.9), numeric(0), NULL);range(argv[[1]][[1]],argv[[1]][[2]],argv[[1]][[3]],argv[[1]][[4]], na.rm = FALSE);"); } @Test public void testrange8() { - assertEval(Output.IgnoreErrorContext, "argv <- list(structure(c(3L, 2L, 1L), .Label = c('A', 'B', 'C'), class = c('ordered', 'factor')), na.rm = FALSE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(3L, 2L, 1L), .Label = c('A', 'B', 'C'), class = c('ordered', 'factor')));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testrange9() { - assertEval(Output.IgnoreErrorContext, - "argv <- list(structure(list(sec = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), min = c(40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L), hour = c(8L, 8L, 9L, 9L, 9L, 9L, 9L, 9L, 10L, 10L, 10L, 10L, 10L, 10L, 11L, 11L, 11L, 11L, 11L, 11L, 12L, 12L, 12L, 12L, 12L, 12L, 13L, 13L, 13L, 13L, 13L, 13L, 14L, 14L, 14L, 14L, 14L, 14L, 15L, 15L, 15L, 15L, 15L, 15L, 16L, 16L, 16L, 16L, 16L, 16L, 17L, 17L, 17L, 17L, 17L, 17L, 18L, 18L, 18L, 18L, 18L, 18L, 19L, 19L, 19L, 19L, 19L, 19L, 20L, 20L, 20L, 20L, 20L, 20L, 21L, 21L, 21L, 21L, 21L, 21L, 22L, 22L, 22L, 22L, 22L, 23L, 23L, 23L, 23L, 23L, 23L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L), mday = c(12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L), mon = c(11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L), year = c(90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L), wday = c(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, 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, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L), yday = c(345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L), isdst = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L)), .Names = c('sec', 'min', 'hour', 'mday', 'mon', 'year', 'wday', 'yday', 'isdst'), class = c('POSIXlt', 'POSIXt')), na.rm = FALSE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(list(sec = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), min = c(40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L, 50L, 0L, 10L, 20L, 30L, 40L), hour = c(8L, 8L, 9L, 9L, 9L, 9L, 9L, 9L, 10L, 10L, 10L, 10L, 10L, 10L, 11L, 11L, 11L, 11L, 11L, 11L, 12L, 12L, 12L, 12L, 12L, 12L, 13L, 13L, 13L, 13L, 13L, 13L, 14L, 14L, 14L, 14L, 14L, 14L, 15L, 15L, 15L, 15L, 15L, 15L, 16L, 16L, 16L, 16L, 16L, 16L, 17L, 17L, 17L, 17L, 17L, 17L, 18L, 18L, 18L, 18L, 18L, 18L, 19L, 19L, 19L, 19L, 19L, 19L, 20L, 20L, 20L, 20L, 20L, 20L, 21L, 21L, 21L, 21L, 21L, 21L, 22L, 22L, 22L, 22L, 22L, 23L, 23L, 23L, 23L, 23L, 23L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L), mday = c(12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L), mon = c(11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L), year = c(90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L, 90L), wday = c(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, 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, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L), yday = c(345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 345L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L, 346L), isdst = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L)), .Names = c('sec', 'min', 'hour', 'mday', 'mon', 'year', 'wday', 'yday', 'isdst'), class = c('POSIXlt', 'POSIXt')));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testrange10() { - assertEval("argv <- list(structure(c(-3.5527136788005e-14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6.21724893790088e-15, -1.77635683940025e-15, -8.88178419700125e-16, -1.33226762955019e-15, -1.22124532708767e-15, -8.88178419700125e-16, -1.33226762955019e-15, -1.22124532708767e-15, -1.33226762955019e-15, -1.11022302462516e-15, -8.88178419700125e-16, -1.33226762955019e-15, -8.88178419700125e-16, -8.88178419700125e-16, -4.44089209850063e-16, -4.44089209850063e-16, -1.22124532708767e-15, -1.22124532708767e-15, -8.88178419700125e-16, -1.33226762955019e-15, -8.88178419700125e-16, -4.44089209850063e-16, -6.66133814775094e-16, -7.7715611723761e-16, -4.44089209850063e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -1.33226762955019e-15, -1.33226762955019e-15, -1.33226762955019e-15, -8.88178419700125e-16, -1.11022302462516e-15, -4.44089209850063e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -1.33226762955019e-15, -1.33226762955019e-15, -8.88178419700125e-16, -4.44089209850063e-16, -1.22124532708767e-15, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -1.33226762955019e-15, -1.22124532708767e-15, 5.91171556152403e-12, -1.59161572810262e-12, 4.54747350886464e-13, 1.02318153949454e-12, 1.13686837721616e-12, 4.54747350886464e-13, 9.09494701772928e-13, 9.09494701772928e-13, 1.02318153949454e-12, 9.09494701772928e-13, 0, 9.09494701772928e-13, 4.54747350886464e-13, 0, 0, 3.41060513164848e-13, 9.66338120633736e-13, 1.19371179607697e-12, 2.27373675443232e-13, 9.66338120633736e-13, 2.27373675443232e-13, 0, 4.54747350886464e-13, 9.66338120633736e-13, 0, 6.82121026329696e-13, 4.54747350886464e-13, 2.27373675443232e-13, 4.54747350886464e-13, 1.08002495835535e-12, 1.02318153949454e-12, 8.5265128291212e-13, 7.38964445190504e-13, 9.09494701772928e-13, 4.54747350886464e-13, 5.6843418860808e-13, 7.105427357601e-13, 3.41060513164848e-13, 0, 0, 9.66338120633736e-13, 1.02318153949454e-12, 0, 4.54747350886464e-13, 1.13686837721616e-12, 1.05160324892495e-12, 9.09494701772928e-13, 3.41060513164848e-13, 8.38440428196918e-13, 1.4210854715202e-12, 1.15463194561016e-14, -8.88178419700125e-16, -1.33226762955019e-15, -2.02615701994091e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 8.88178419700125e-16, 2.22044604925031e-15, 1.77635683940025e-15, 0, 1.33226762955019e-15, 8.88178419700125e-16, 2.22044604925031e-15, 2.22044604925031e-15, 1.77635683940025e-15, 1.77635683940025e-15, 8.88178419700125e-16, 4.44089209850063e-16, 0, 1.77635683940025e-15, 8.88178419700125e-16, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.11022302462516e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.55431223447522e-15, 1.66533453693773e-15, 2.66453525910038e-15, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 1.77635683940025e-15, 2.22044604925031e-15, 8.88178419700125e-16, 2.22044604925031e-15, 3.77475828372553e-15, 1.77635683940025e-15, 0, 1.33226762955019e-15, 0, 2.66453525910038e-15), .Dim = c(50L, 4L), .Dimnames = list(c('Australia', 'Austria', 'Belgium', 'Bolivia', 'Brazil', 'Canada', 'Chile', 'China', 'Colombia', 'Costa Rica', 'Denmark', 'Ecuador', 'Finland', 'France', 'Germany', 'Greece', 'Guatamala', 'Honduras', 'Iceland', 'India', 'Ireland', 'Italy', 'Japan', 'Korea', 'Luxembourg', 'Malta', 'Norway', 'Netherlands', 'New Zealand', 'Nicaragua', 'Panama', 'Paraguay', 'Peru', 'Philippines', 'Portugal', 'South Africa', 'South Rhodesia', 'Spain', 'Sweden', 'Switzerland', 'Turkey', 'Tunisia', 'United Kingdom', 'United States', 'Venezuela', 'Zambia', 'Jamaica', 'Uruguay', 'Libya', 'Malaysia'), c('pop15', 'pop75', 'dpi', 'ddpi'))), na.rm = FALSE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(-3.5527136788005e-14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6.21724893790088e-15, -1.77635683940025e-15, -8.88178419700125e-16, -1.33226762955019e-15, -1.22124532708767e-15, -8.88178419700125e-16, -1.33226762955019e-15, -1.22124532708767e-15, -1.33226762955019e-15, -1.11022302462516e-15, -8.88178419700125e-16, -1.33226762955019e-15, -8.88178419700125e-16, -8.88178419700125e-16, -4.44089209850063e-16, -4.44089209850063e-16, -1.22124532708767e-15, -1.22124532708767e-15, -8.88178419700125e-16, -1.33226762955019e-15, -8.88178419700125e-16, -4.44089209850063e-16, -6.66133814775094e-16, -7.7715611723761e-16, -4.44089209850063e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -1.33226762955019e-15, -1.33226762955019e-15, -1.33226762955019e-15, -8.88178419700125e-16, -1.11022302462516e-15, -4.44089209850063e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -1.33226762955019e-15, -1.33226762955019e-15, -8.88178419700125e-16, -4.44089209850063e-16, -1.22124532708767e-15, -8.88178419700125e-16, -8.88178419700125e-16, -8.88178419700125e-16, -1.33226762955019e-15, -1.22124532708767e-15, 5.91171556152403e-12, -1.59161572810262e-12, 4.54747350886464e-13, 1.02318153949454e-12, 1.13686837721616e-12, 4.54747350886464e-13, 9.09494701772928e-13, 9.09494701772928e-13, 1.02318153949454e-12, 9.09494701772928e-13, 0, 9.09494701772928e-13, 4.54747350886464e-13, 0, 0, 3.41060513164848e-13, 9.66338120633736e-13, 1.19371179607697e-12, 2.27373675443232e-13, 9.66338120633736e-13, 2.27373675443232e-13, 0, 4.54747350886464e-13, 9.66338120633736e-13, 0, 6.82121026329696e-13, 4.54747350886464e-13, 2.27373675443232e-13, 4.54747350886464e-13, 1.08002495835535e-12, 1.02318153949454e-12, 8.5265128291212e-13, 7.38964445190504e-13, 9.09494701772928e-13, 4.54747350886464e-13, 5.6843418860808e-13, 7.105427357601e-13, 3.41060513164848e-13, 0, 0, 9.66338120633736e-13, 1.02318153949454e-12, 0, 4.54747350886464e-13, 1.13686837721616e-12, 1.05160324892495e-12, 9.09494701772928e-13, 3.41060513164848e-13, 8.38440428196918e-13, 1.4210854715202e-12, 1.15463194561016e-14, -8.88178419700125e-16, -1.33226762955019e-15, -2.02615701994091e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 8.88178419700125e-16, 2.22044604925031e-15, 1.77635683940025e-15, 0, 1.33226762955019e-15, 8.88178419700125e-16, 2.22044604925031e-15, 2.22044604925031e-15, 1.77635683940025e-15, 1.77635683940025e-15, 8.88178419700125e-16, 4.44089209850063e-16, 0, 1.77635683940025e-15, 8.88178419700125e-16, 1.77635683940025e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.11022302462516e-15, 1.77635683940025e-15, 1.77635683940025e-15, 1.55431223447522e-15, 1.66533453693773e-15, 2.66453525910038e-15, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 8.88178419700125e-16, 1.77635683940025e-15, 2.22044604925031e-15, 8.88178419700125e-16, 2.22044604925031e-15, 3.77475828372553e-15, 1.77635683940025e-15, 0, 1.33226762955019e-15, 0, 2.66453525910038e-15), .Dim = c(50L, 4L), .Dimnames = list(c('Australia', 'Austria', 'Belgium', 'Bolivia', 'Brazil', 'Canada', 'Chile', 'China', 'Colombia', 'Costa Rica', 'Denmark', 'Ecuador', 'Finland', 'France', 'Germany', 'Greece', 'Guatamala', 'Honduras', 'Iceland', 'India', 'Ireland', 'Italy', 'Japan', 'Korea', 'Luxembourg', 'Malta', 'Norway', 'Netherlands', 'New Zealand', 'Nicaragua', 'Panama', 'Paraguay', 'Peru', 'Philippines', 'Portugal', 'South Africa', 'South Rhodesia', 'Spain', 'Sweden', 'Switzerland', 'Turkey', 'Tunisia', 'United Kingdom', 'United States', 'Venezuela', 'Zambia', 'Jamaica', 'Uruguay', 'Libya', 'Malaysia'), c('pop15', 'pop75', 'dpi', 'ddpi'))));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testrange11() { - assertEval(Output.IgnoreErrorContext, - "argv <- list(structure(c(4L, 5L, 1L, 5L, 3L, 4L, 5L, 3L, 2L, 4L), .Label = c('a', 'c', 'i', 's', 't'), class = c('ordered', 'factor')), structure(c(4L, 2L, 3L, 5L, 4L, 3L, 5L, 1L, 5L, 4L), .Label = c('a', 'c', 'i', 's', 't'), class = c('ordered', 'factor')), na.rm = FALSE);range(argv[[1]],argv[[2]],argv[[3]]);"); + assertEval("argv <- list(structure(c(4L, 5L, 1L, 5L, 3L, 4L, 5L, 3L, 2L, 4L), .Label = c('a', 'c', 'i', 's', 't'), class = c('ordered', 'factor')), structure(c(4L, 2L, 3L, 5L, 4L, 3L, 5L, 1L, 5L, 4L), .Label = c('a', 'c', 'i', 's', 't'), class = c('ordered', 'factor')));range(argv[[1]][[1]],argv[[1]][[2]],argv[[1]][[3]], na.rm = FALSE);"); } @Test public void testrange12() { - assertEval("argv <- list(structure(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, 94, 95, 96, 97, 98, 99, 100, 101), .Tsp = c(1, 101, 1), class = 'ts'), na.rm = FALSE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(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, 94, 95, 96, 97, 98, 99, 100, 101), .Tsp = c(1, 101, 1), class = 'ts'));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testrange13() { - assertEval("argv <- list(c(NA, 1, 2, 3, -Inf, NaN, Inf), na.rm = FALSE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(c(NA, 1, 2, 3, -Inf, NaN, Inf));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testrange14() { - assertEval("argv <- list(c(14.43333, 65.7667), finite = TRUE, na.rm = FALSE);range(argv[[1]],argv[[2]],argv[[3]]);"); + assertEval("argv <- list(c(14.43333, 65.7667), finite = TRUE);range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testrange15() { - assertEval("argv <- list(structure(c(1, 13, 31), .Dim = 3L, .Dimnames = list(c('1st', '2nd', '3rd'))), finite = TRUE, na.rm = FALSE);range(argv[[1]],argv[[2]],argv[[3]]);"); - } - - @Test - public void testrange16() { - assertEval(Ignored.Unknown, "argv <- list(list(), na.rm = TRUE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(1, 13, 31), .Dim = 3L, .Dimnames = list(c('1st', '2nd', '3rd'))), finite = TRUE);range(argv[[1]][[1]],argv[[1]][[2]],argv[[1]][[3]], na.rm = FALSE);"); } @Test public void testrange17() { - assertEval("argv <- list(structure(c(1012633320L, 1012633620L), class = c('POSIXct', 'POSIXt'), tzone = ''), na.rm = TRUE);range(argv[[1]],argv[[2]]);"); - } - - @Test - public void testrange18() { - assertEval("argv <- list(structure(numeric(0), .Dim = c(0L, 0L)), na.rm = FALSE);range(argv[[1]],argv[[2]]);"); - } - - @Test - public void testrange19() { - assertEval("argv <- list(structure(logical(0), .Dim = c(0L, 0L), .Dimnames = list(NULL, NULL)), na.rm = FALSE);range(argv[[1]],argv[[2]]);"); + assertEval(Ignored.ImplementationError, "argv <- list(structure(c(1012633320L, 1012633620L), class = c('POSIXct', 'POSIXt'), tzone = ''));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE);"); } @Test public void testrange20() { - assertEval("argv <- list(c(2.00256647265648e-308, 2.22284878464869e-308, 2.22507363599982e-308, 2.2250738585072e-308, 2.22507408101459e-308, 2.22729893236571e-308, 2.44758124435792e-308), na.rm = FALSE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(c(2.00256647265648e-308, 2.22284878464869e-308, 2.22507363599982e-308, 2.2250738585072e-308, 2.22507408101459e-308, 2.22729893236571e-308, 2.44758124435792e-308));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testrange21() { - assertEval("argv <- list(structure(c(12053, 12054, 12055, 12056, 12057, 12058, 12059, 12060, 12061, 12062), class = 'Date'), na.rm = TRUE);range(argv[[1]],argv[[2]]);"); + assertEval(Ignored.ImplementationError, + "argv <- list(structure(c(12053, 12054, 12055, 12056, 12057, 12058, 12059, 12060, 12061, 12062), class = 'Date'));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE);"); } @Test public void testrange22() { - assertEval("argv <- list(structure(c(1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, NA, 1L, 1L, 2L, 1L, 1L, NA, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, NA, 2L, 2L, 1L, NA, 2L, 2L, NA, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 1L), .Dim = c(20L, 6L), .Dimnames = list(c('ant', 'bee', 'cat', 'cpl', 'chi', 'cow', 'duc', 'eag', 'ele', 'fly', 'fro', 'her', 'lio', 'liz', 'lob', 'man', 'rab', 'sal', 'spi', 'wha'), c('war', 'fly', 'ver', 'end', 'gro', 'hai'))), na.rm = TRUE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, NA, 1L, 1L, 2L, 1L, 1L, NA, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, NA, 2L, 2L, 1L, NA, 2L, 2L, NA, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 1L), .Dim = c(20L, 6L), .Dimnames = list(c('ant', 'bee', 'cat', 'cpl', 'chi', 'cow', 'duc', 'eag', 'ele', 'fly', 'fro', 'her', 'lio', 'liz', 'lob', 'man', 'rab', 'sal', 'spi', 'wha'), c('war', 'fly', 'ver', 'end', 'gro', 'hai'))));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE);"); } @Test public void testrange23() { - assertEval("argv <- list(structure(c(13823, NA), class = 'Date'), na.rm = TRUE);range(argv[[1]],argv[[2]]);"); + assertEval(Ignored.ImplementationError, "argv <- list(structure(c(13823, NA), class = 'Date'));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE);"); } @Test @@ -141,37 +125,37 @@ public class TestBuiltin_range extends TestBase { @Test public void testrange25() { - assertEval("argv <- list(structure(c(1949, 1949.08333333333, 1949.16666666667, 1949.25, 1949.33333333333, 1949.41666666667, 1949.5, 1949.58333333333, 1949.66666666667, 1949.75, 1949.83333333333, 1949.91666666667, 1950, 1950.08333333333, 1950.16666666667, 1950.25, 1950.33333333333, 1950.41666666667, 1950.5, 1950.58333333333, 1950.66666666667, 1950.75, 1950.83333333333, 1950.91666666667, 1951, 1951.08333333333, 1951.16666666667, 1951.25, 1951.33333333333, 1951.41666666667, 1951.5, 1951.58333333333, 1951.66666666667, 1951.75, 1951.83333333333, 1951.91666666667, 1952, 1952.08333333333, 1952.16666666667, 1952.25, 1952.33333333333, 1952.41666666667, 1952.5, 1952.58333333333, 1952.66666666667, 1952.75, 1952.83333333333, 1952.91666666667, 1953, 1953.08333333333, 1953.16666666667, 1953.25, 1953.33333333333, 1953.41666666667, 1953.5, 1953.58333333333, 1953.66666666667, 1953.75, 1953.83333333333, 1953.91666666667, 1954, 1954.08333333333, 1954.16666666667, 1954.25, 1954.33333333333, 1954.41666666667, 1954.5, 1954.58333333333, 1954.66666666667, 1954.75, 1954.83333333333, 1954.91666666667, 1955, 1955.08333333333, 1955.16666666667, 1955.25, 1955.33333333333, 1955.41666666667, 1955.5, 1955.58333333333, 1955.66666666667, 1955.75, 1955.83333333333, 1955.91666666667, 1956, 1956.08333333333, 1956.16666666667, 1956.25, 1956.33333333333, 1956.41666666667, 1956.5, 1956.58333333333, 1956.66666666667, 1956.75, 1956.83333333333, 1956.91666666667, 1957, 1957.08333333333, 1957.16666666667, 1957.25, 1957.33333333333, 1957.41666666667, 1957.5, 1957.58333333333, 1957.66666666667, 1957.75, 1957.83333333333, 1957.91666666667, 1958, 1958.08333333333, 1958.16666666667, 1958.25, 1958.33333333333, 1958.41666666667, 1958.5, 1958.58333333333, 1958.66666666667, 1958.75, 1958.83333333333, 1958.91666666667, 1959, 1959.08333333333, 1959.16666666667, 1959.25, 1959.33333333333, 1959.41666666667, 1959.5, 1959.58333333333, 1959.66666666667, 1959.75, 1959.83333333333, 1959.91666666667, 1960, 1960.08333333333, 1960.16666666667, 1960.25, 1960.33333333333, 1960.41666666667, 1960.5, 1960.58333333333, 1960.66666666667, 1960.75, 1960.83333333333, 1960.91666666667, 1961, 1961.08333333333, 1961.16666666667, 1961.25, 1961.33333333333, 1961.41666666667, 1961.5, 1961.58333333333, 1961.66666666667, 1961.75, 1961.83333333333, 1961.91666666667, 1962, 1962.08333333333, 1962.16666666667, 1962.25, 1962.33333333333, 1962.41666666667, 1962.5, 1962.58333333333, 1962.66666666667, 1962.75, 1962.83333333333, 1962.91666666667), .Tsp = c(1949, 1962.91666666667, 12), class = 'ts'), na.rm = FALSE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(1949, 1949.08333333333, 1949.16666666667, 1949.25, 1949.33333333333, 1949.41666666667, 1949.5, 1949.58333333333, 1949.66666666667, 1949.75, 1949.83333333333, 1949.91666666667, 1950, 1950.08333333333, 1950.16666666667, 1950.25, 1950.33333333333, 1950.41666666667, 1950.5, 1950.58333333333, 1950.66666666667, 1950.75, 1950.83333333333, 1950.91666666667, 1951, 1951.08333333333, 1951.16666666667, 1951.25, 1951.33333333333, 1951.41666666667, 1951.5, 1951.58333333333, 1951.66666666667, 1951.75, 1951.83333333333, 1951.91666666667, 1952, 1952.08333333333, 1952.16666666667, 1952.25, 1952.33333333333, 1952.41666666667, 1952.5, 1952.58333333333, 1952.66666666667, 1952.75, 1952.83333333333, 1952.91666666667, 1953, 1953.08333333333, 1953.16666666667, 1953.25, 1953.33333333333, 1953.41666666667, 1953.5, 1953.58333333333, 1953.66666666667, 1953.75, 1953.83333333333, 1953.91666666667, 1954, 1954.08333333333, 1954.16666666667, 1954.25, 1954.33333333333, 1954.41666666667, 1954.5, 1954.58333333333, 1954.66666666667, 1954.75, 1954.83333333333, 1954.91666666667, 1955, 1955.08333333333, 1955.16666666667, 1955.25, 1955.33333333333, 1955.41666666667, 1955.5, 1955.58333333333, 1955.66666666667, 1955.75, 1955.83333333333, 1955.91666666667, 1956, 1956.08333333333, 1956.16666666667, 1956.25, 1956.33333333333, 1956.41666666667, 1956.5, 1956.58333333333, 1956.66666666667, 1956.75, 1956.83333333333, 1956.91666666667, 1957, 1957.08333333333, 1957.16666666667, 1957.25, 1957.33333333333, 1957.41666666667, 1957.5, 1957.58333333333, 1957.66666666667, 1957.75, 1957.83333333333, 1957.91666666667, 1958, 1958.08333333333, 1958.16666666667, 1958.25, 1958.33333333333, 1958.41666666667, 1958.5, 1958.58333333333, 1958.66666666667, 1958.75, 1958.83333333333, 1958.91666666667, 1959, 1959.08333333333, 1959.16666666667, 1959.25, 1959.33333333333, 1959.41666666667, 1959.5, 1959.58333333333, 1959.66666666667, 1959.75, 1959.83333333333, 1959.91666666667, 1960, 1960.08333333333, 1960.16666666667, 1960.25, 1960.33333333333, 1960.41666666667, 1960.5, 1960.58333333333, 1960.66666666667, 1960.75, 1960.83333333333, 1960.91666666667, 1961, 1961.08333333333, 1961.16666666667, 1961.25, 1961.33333333333, 1961.41666666667, 1961.5, 1961.58333333333, 1961.66666666667, 1961.75, 1961.83333333333, 1961.91666666667, 1962, 1962.08333333333, 1962.16666666667, 1962.25, 1962.33333333333, 1962.41666666667, 1962.5, 1962.58333333333, 1962.66666666667, 1962.75, 1962.83333333333, 1962.91666666667), .Tsp = c(1949, 1962.91666666667, 12), class = 'ts'));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testrange26() { - assertEval("argv <- list(c(1.47191076131574, 0.586694550701453, 0.258706725324317, 0.948371836939988, 0.396080061109718, 0.350912037541581), finite = TRUE, na.rm = FALSE);range(argv[[1]],argv[[2]],argv[[3]]);"); + assertEval("argv <- list(c(1.47191076131574, 0.586694550701453, 0.258706725324317, 0.948371836939988, 0.396080061109718, 0.350912037541581), finite = TRUE);range(argv[[1]][[1]],argv[[1]][[2]],argv[[1]][[3]], na.rm = FALSE);"); } @Test public void testrange27() { - assertEval("argv <- list(structure(c(-11.3814849918875, -11.9361690778798, 0.562602893455921, 11.5126028934559, 76.2209544348296, -8.66448499188751, -6.94502893455923, -5.28148499188751, -35.7665182531098, 6.35497106544077, -9.20908119253651, -0.898484991887508, -5.59380090589508, -6.12730922120065, -13.3061334505138, 58.6278831800973, -15.1098009058951, -8.29625696322337, -4.07211681990265, 3.7096551514332, 2.60151500811249, 6.24733923742563, -1.33911681990266, -2.14157287723094, -10.5984849918875, -8.12802893455923, 1.30028697944835, -15.7450289345592, 7.20569077879935, -12.6484849918875, 25.1810423201731, -4.42680090589508, -1.90886979448351), .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')), na.rm = TRUE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(-11.3814849918875, -11.9361690778798, 0.562602893455921, 11.5126028934559, 76.2209544348296, -8.66448499188751, -6.94502893455923, -5.28148499188751, -35.7665182531098, 6.35497106544077, -9.20908119253651, -0.898484991887508, -5.59380090589508, -6.12730922120065, -13.3061334505138, 58.6278831800973, -15.1098009058951, -8.29625696322337, -4.07211681990265, 3.7096551514332, 2.60151500811249, 6.24733923742563, -1.33911681990266, -2.14157287723094, -10.5984849918875, -8.12802893455923, 1.30028697944835, -15.7450289345592, 7.20569077879935, -12.6484849918875, 25.1810423201731, -4.42680090589508, -1.90886979448351), .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')));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE);"); } @Test public void testrange28() { - assertEval("argv <- list(c(9.5367431640625e-07, 1.9073486328125e-06, 3.814697265625e-06, 7.62939453125e-06, 1.52587890625e-05, 3.0517578125e-05, 6.103515625e-05, 0.0001220703125, 0.000244140625, 0.00048828125, 0.0009765625, 0.001953125, 0.00390625, 0.0078125, 0.015625, 0.03125, 0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024), na.rm = FALSE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(c(9.5367431640625e-07, 1.9073486328125e-06, 3.814697265625e-06, 7.62939453125e-06, 1.52587890625e-05, 3.0517578125e-05, 6.103515625e-05, 0.0001220703125, 0.000244140625, 0.00048828125, 0.0009765625, 0.001953125, 0.00390625, 0.0078125, 0.015625, 0.03125, 0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testrange29() { assertEval(Ignored.Unknown, - "argv <- list(structure(c(1208822400, 1209168000, 1208822400, 1209168000), class = c('POSIXct', 'POSIXt'), tzone = 'GMT'), na.rm = TRUE);range(argv[[1]],argv[[2]]);"); + "argv <- list(structure(c(1208822400, 1209168000, 1208822400, 1209168000), class = c('POSIXct', 'POSIXt'), tzone = 'GMT'));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE);"); } @Test public void testrange30() { - assertEval("argv <- list(c(1.86606598307361, 339033474310168, 6.15968019059533e+28, 1.11911250438065e+43, 2.03324321833028e+57, 3.69406826275609e+71, 6.71151400229846e+85, 1.21937162496937e+100, 2.2153975381282e+114, 4.02501267984465e+128, 7.31278553581751e+142, 1.32861276588395e+157, 2.41387071044804e+171, 4.38560576593759e+185, 7.96792382084694e+199, 1.44764060891943e+214, 2.63012470966353e+228, 4.77850368783602e+242, 8.6817546752692e+256, 1.57733192575377e+271), na.rm = FALSE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(c(1.86606598307361, 339033474310168, 6.15968019059533e+28, 1.11911250438065e+43, 2.03324321833028e+57, 3.69406826275609e+71, 6.71151400229846e+85, 1.21937162496937e+100, 2.2153975381282e+114, 4.02501267984465e+128, 7.31278553581751e+142, 1.32861276588395e+157, 2.41387071044804e+171, 4.38560576593759e+185, 7.96792382084694e+199, 1.44764060891943e+214, 2.63012470966353e+228, 4.77850368783602e+242, 8.6817546752692e+256, 1.57733192575377e+271));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);"); } @Test public void testrange31() { - assertEval("argv <- list(structure(c(1, 0.666666666666667, 0.333333333333333, 0, -0.333333333333333, -0.666666666666667, -1, -1.33333333333333, -1.66666666666667, 1.5, 1, 0.5, 0, -0.5, -1, -1.5, -2, -2.5, 3, 2, 1, 0, -1, -2, -3, -4, -5, -Inf, -Inf, -Inf, NaN, Inf, Inf, Inf, Inf, Inf, -3, -2, -1, 0, 1, 2, 3, 4, 5, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, -1, -0.666666666666667, -0.333333333333333, 0, 0.333333333333333, 0.666666666666667, 1, 1.33333333333333, 1.66666666666667, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1, 1.25, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1), .Dim = c(9L, 9L)), na.rm = TRUE);range(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(structure(c(1, 0.666666666666667, 0.333333333333333, 0, -0.333333333333333, -0.666666666666667, -1, -1.33333333333333, -1.66666666666667, 1.5, 1, 0.5, 0, -0.5, -1, -1.5, -2, -2.5, 3, 2, 1, 0, -1, -2, -3, -4, -5, -Inf, -Inf, -Inf, NaN, Inf, Inf, Inf, Inf, Inf, -3, -2, -1, 0, 1, 2, 3, 4, 5, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, -1, -0.666666666666667, -0.333333333333333, 0, 0.333333333333333, 0.666666666666667, 1, 1.33333333333333, 1.66666666666667, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1, 1.25, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1), .Dim = c(9L, 9L)));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = TRUE);"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rank.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rank.java index 6cef0b8e2653a1374f165ba816fabe68b489ed68..6d2c0d341e2f16777ae15837b3e50263a65d9663 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rank.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rank.java @@ -85,4 +85,11 @@ public class TestBuiltin_rank extends TestBase { assertEval("{ rank(c(a=1,b=1,c=3,d=NA,e=3), na.last=NA, ties.method=\"min\") }"); assertEval("{ rank(c(1000, 100, 100, NA, 1, 20), ties.method=\"first\") }"); } + + @Test + public void testArgsCasts() { + assertEval(".Internal(rank(c(1,2), -3L, 'max'))"); + assertEval(".Internal(rank(c(1,2), 2L, 'something'))"); + assertEval(".Internal(rank(as.raw(42), 42L, 'max'))"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java index 49eb602222d8a9674bfd052307eda5dd6d57d962..cc015b626e7f354526767108c36ad73f42f38eac 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java @@ -69,5 +69,7 @@ public class TestBuiltin_rbind extends TestBase { assertEval("{ info <- c(\"print\", \"AES\", \"print.AES\") ; ns <- integer(0) ; rbind(info, ns) }"); assertEval("{ x<-list(a=7, b=NULL, c=42); y<-as.data.frame(do.call(rbind,x)); y }"); + + assertEval("{ x<-data.frame(c(1,2),c(3,4)); dimnames(x) <- list(c(\"A\", \"B\"), c(\"C\", \"D\")); rbind(x) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_regexpr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_regexpr.java index d0af20a2ac660aa0f515e4c91db64514caa41f54..ae591ffaba1c26eaffc1b4ff728eb1d2ce6cd671 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_regexpr.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_regexpr.java @@ -99,5 +99,14 @@ public class TestBuiltin_regexpr extends TestBase { assertEval("{ x<-regexpr(\"aaa\", c(\"bbbaaaccc\", \"hah\"), fixed=TRUE); c(x[1], x[2]) }"); assertEval("{ x <- \"methods.html\"; pos <- regexpr(\"\\\\.([[:alnum:]]+)$\", x); substring(x, pos + 1L) }"); + + assertEval("{ as.integer(regexpr(\"foo\", c(\"bar foo foo\", \"foo\"), fixed=T)) }"); + assertEval("{ as.integer(regexpr(\"foo\", c(\"bar foo foo\", \"foo\"), fixed=F)) }"); + assertEval("{ x<-regexpr(\"foo\", c(\"bar foo foo\", \"foo\"), fixed=T); attr(x, \"match.length\") }"); + assertEval("{ x<-regexpr(\"foo\", c(\"bar foo foo\", \"foo\")); attr(x, \"match.length\") }"); + + assertEval("{ .Internal(regexpr(7, \"42\", F, F, F, F)) }"); + assertEval("{ .Internal(regexpr(character(), \"42\", F, F, F, F)) }"); + assertEval("{ .Internal(regexpr(\"7\", 42, F, F, F, F)) }"); } } 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 06232e5ec9d69e7a7ec915c0b1e85cdffb102bd6..e15b21ddd44e6d74bbb05bfb1eed47b911f40924 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 @@ -199,5 +199,24 @@ public class TestBuiltin_rep extends TestBase { assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); rep(x, length=5) }"); assertEval("rep(x<-42)"); + + assertEval(Output.IgnoreErrorContext, "{ rep(function() 42) }"); + assertEval("{ rep(7, times=character()) }"); + 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=NA) }"); + assertEval("{ rep(7, length.out=NULL) }"); + assertEval(Output.IgnoreWarningContext, "{ rep(7, length.out=c(7, 42)) }"); + assertEval("{ rep(7, each=\"7\") }"); + assertEval("{ rep(7, each=integer()) }"); + assertEval("{ rep(7, each=NA) }"); + assertEval("{ rep(7, each=NULL) }"); + assertEval("{ rep(7, each=c(7, 42)) }"); + assertEval("{ rep(7, times=NA) }"); + assertEval("{ rep(7, times=-1) }"); + assertEval("{ rep(c(7, 42), times=c(2, NA)) }"); + assertEval(Output.IgnoreWarningContext, "{ rep(7, times=\"foo\") }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep_len.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep_len.java index 5c4ed8dcecc3b9967b1951f0856a99179846dc0a..a2225e026a21cec3caf2e512d6d5be12bb0a1826 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep_len.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep_len.java @@ -47,5 +47,13 @@ public class TestBuiltin_rep_len extends TestBase { assertEval("{rep_len(c(\"abcd\", \"efg\"), 0)}"); assertEval("{rep_len(c(\"abcd\", \"efg\"), 1)}"); assertEval("{rep_len(c(\"abcd\", \"efg\"), 2)}"); + + assertEval(Output.IgnoreErrorContext, "{ rep_len(function() 42, 7) }"); + assertEval("{ rep_len(7, \"7\") }"); + assertEval("{ rep_len(7, integer()) }"); + assertEval("{ rep_len(7, NA) }"); + assertEval("{ rep_len(7, NULL) }"); + assertEval("{ rep_len(7, c(7, 42)) }"); + } } 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 95d6a0a9cd40ffe2560e2adff9771087c70da314..814d34bb3a8b387cee833b1dbf5a5297ba6e13bc 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 @@ -165,5 +165,13 @@ public class TestBuiltin_repint extends TestBase { assertEval("{ rep.int(seq_len(2), rep.int(8, 2)) }"); assertEval(Output.IgnoreErrorContext, "{ 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, function() 42) }"); + assertEval(Output.IgnoreErrorContext, "{ rep.int(7, NA) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rm.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rm.java new file mode 100644 index 0000000000000000000000000000000000000000..15ac77f83a1e5334aa682d597a9de56d8068e55a --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rm.java @@ -0,0 +1,46 @@ +/* + * 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.test.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestBuiltin_rm extends TestBase { + @Test + public void basicTests() { + assertEval("tmp <- 42; rm(tmp); tmp"); + assertEval("tmp <- 42; rm(list='tmp'); tmp"); + assertEval(" e <- new.env(); e$a <- 42; rm(list='a', envir=e); e$a"); + assertEval(Output.IgnoreErrorContext, "tmp <- 42; f <- function() rm(list='tmp',inherits=T); f(); tmp"); + } + + @Test + public void testArgsCasting() { + assertEval("tmp <- 42; rm(tmp, inherits='asd')"); + assertEval(".Internal(remove(list=33, environment(), F))"); + assertEval("tmp <- 42; rm(tmp, envir=NULL)"); + assertEval("tmp <- 42; rm(tmp, envir=42)"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_row.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_row.java index 7f9604666f2001e9c8a6d0414c40d9f9c765fb71..e0fcedf85949acbb99019f99a3a809363cd754af 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_row.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_row.java @@ -31,4 +31,9 @@ public class TestBuiltin_row extends TestBase { public void testrow3() { assertEval("argv <- list(0:1); .Internal(row(argv[[1]]))"); } + + @Test + public void testArgsCasts() { + assertEval(".Internal(row('str'))"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowMeans.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowMeans.java index 8e14c8b34e15ed811d87e96d40a22fa66abbae11..7f85178c0b2a08ebef095085aa7f48bdd0183d04 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowMeans.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowMeans.java @@ -58,8 +58,9 @@ public class TestBuiltin_rowMeans extends TestBase { // Whichever value(NA or NaN) is first in the row will be returned for that row. assertEval("{rowMeans(matrix(c(NA,NaN,NaN,NA),ncol=2,nrow=2))}"); - // Error message mismatch + assertEval("{x<-matrix(c(\"1\",\"2\",\"3\",\"4\"),ncol=2);rowMeans(x)}"); + assertEval("{rowMeans(matrix(c(NaN,4+5i,2+0i,5+10i),nrow=2,ncol=2), na.rm = FALSE)}"); + // Internal error in matrix(NA, NA, NA) assertEval(Ignored.Unknown, "{rowMeans(matrix(NA,NA,NA),TRUE)}"); - assertEval(Output.IgnoreErrorContext, "{x<-matrix(c(\"1\",\"2\",\"3\",\"4\"),ncol=2);rowMeans(x)}"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowSums.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowSums.java index a84133cafbc91f3cb1142ae9109ee5ce11322f7c..728dda3c30e2c663b7b4b55576de79a2559a71db 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowSums.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowSums.java @@ -100,6 +100,6 @@ public class TestBuiltin_rowSums extends TestBase { // rowSums on array have correct values assertEval("{ a = rowSums(array(1:24,c(2,3,4))); c(a[1],a[2]) }"); - assertEval(Output.IgnoreErrorContext, "{x<-matrix(c(\"1\",\"2\",\"3\",\"4\"),ncol=2);rowSums(x)}"); + assertEval("{x<-matrix(c(\"1\",\"2\",\"3\",\"4\"),ncol=2);rowSums(x)}"); } } 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 3854d53c8d8be894920fc8804e46255460d6d39c..fa5190ed610d8497b50dd3f3a2ff5186322223d2 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 @@ -73,4 +73,32 @@ public class TestBuiltin_sample extends TestBase { assertEval(Ignored.Unknown, "{ set.seed(4357, \"default\"); x <- 5 ; sample(x, 6, FALSE, NULL) ;}"); assertEval(Ignored.Unknown, "{ set.seed(9567, \"Marsaglia-Multicarry\"); x <- 5 ; sample(x, 6, FALSE, NULL) ;}"); } + + @Test + public void testArgsCasts() { + // x + assertEval("set.seed(42); sample(-1)"); + 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))"); + // Note: we treat Infinity in NaN check + assertEval(Output.IgnoreErrorMessage, "set.seed(42); .Internal(sample(1/0, 1, FALSE, NULL))"); + // size + assertEval("set.seed(42); sample(3, '2')"); + assertEval("set.seed(42); sample(3, 2.0)"); + assertEval("set.seed(42); sample(3, c(2,3))"); + assertEval("set.seed(42); sample(3, TRUE)"); + assertEval("set.seed(42); sample(3, -3)"); + assertEval("set.seed(42); sample(3, NA)"); + 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=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))"); + } } 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 8e63ca6f7b861db6044a479f640a83e4e08cc0ff..3d0a2e63d3117bb4aabfaba4f442b204a20c3dd1 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 @@ -59,8 +59,7 @@ public class TestBuiltin_sep extends TestBase { @Test public void testsep9() { - assertEval(Ignored.Unknown, - "argv <- list(c(-20.7752893729399+0i, -22.2629231778254+0i, 30.2366932497517-0i, -17.7609104766206+0i, -12.009450871146+0i, -20.6744466063748+0i, -16.2509653806178-0i, 14.8872572302678-0i, -2.41214022512376e+00+5e-15i, 30.1945691318138-0i, -14.86107358966-0i, -75.7334659810725-0i, -31.7348183989382+0i, 33.742775143777-0i, 26.1570616797447-0i, 37.7317903854624+0i, -7.20820970337446-0i, 38.6698755921621-0i, -26.4295844393936-0i, 26.3000016960339+0i, -16.3754767271763+0i, -7.29593605495242-0i, 9.19886724090888+0i, -35.3925832738897+0i, 21.0943018303757+0i, 4.90714440628349-0i), 26L);`/`(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(c(-20.7752893729399+0i, -22.2629231778254+0i, 30.2366932497517-0i, -17.7609104766206+0i, -12.009450871146+0i, -20.6744466063748+0i, -16.2509653806178-0i, 14.8872572302678-0i, -2.41214022512376e+00+5e-15i, 30.1945691318138-0i, -14.86107358966-0i, -75.7334659810725-0i, -31.7348183989382+0i, 33.742775143777-0i, 26.1570616797447-0i, 37.7317903854624+0i, -7.20820970337446-0i, 38.6698755921621-0i, -26.4295844393936-0i, 26.3000016960339+0i, -16.3754767271763+0i, -7.29593605495242-0i, 9.19886724090888+0i, -35.3925832738897+0i, 21.0943018303757+0i, 4.90714440628349-0i), 26L);`/`(argv[[1]],argv[[2]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_len.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_len.java index db975db2c9bcc3d772e20647a81556163884567c..95b9ffe6a890bf5c8965179f106577467a85cf0a 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_len.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_len.java @@ -24,5 +24,10 @@ public class TestBuiltin_seq_len extends TestBase { assertEval("{ seq_len(5L) }"); assertEval("{ seq_len(1:2) }"); assertEval("{ seq_len(integer()) }"); + + assertEval("{ seq_len(NA) }"); + assertEval("{ seq_len(-1) }"); + assertEval("{ seq_len(NULL) }"); + assertEval(Output.IgnoreWarningContext, "{ seq_len(\"foo\") }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setEncoding.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setEncoding.java index b9dc6a94118f29920f901c000df7d318493943a4..5559287ac6bbfaa08e5fdbcf109e44d5bc1370bb 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setEncoding.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setEncoding.java @@ -24,7 +24,7 @@ public class TestBuiltin_setEncoding extends TestBase { @Test public void testsetEncoding2() { - assertEval(Ignored.Unknown, "argv <- list(\''', 'unknown'); .Internal(setEncoding(argv[[1]], argv[[2]]))"); + assertEval(Ignored.Unknown, "argv <- list('', 'unknown'); .Internal(setEncoding(argv[[1]], argv[[2]]))"); } @Test 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 c3eaee2491f0e1c9a895d9849424fa2c695c276a..eeb9eae3cee9a745ea131db97efcf185b99ab545 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 @@ -99,4 +99,15 @@ public class TestBuiltin_setS4Object extends TestBase { assertEval(Ignored.Unknown, "argv <- list(structure(function (x, y, ...) UseMethod('plot'), target = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), defined = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), generic = character(0), class = structure('derivedDefaultMethod', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))"); } + + @Test + public void testSetS4Object() { + assertEval("{ x<-42; asS4(x, \"TRUE\") }"); + assertEval("{ x<-42; asS4(x, logical()) }"); + assertEval("{ x<-42; asS4(x, c(TRUE, FALSE)) }"); + assertEval("{ x<-42; asS4(x, TRUE, \"1\") }"); + assertEval("{ x<-42; asS4(x, TRUE, logical()) }"); + assertEval("{ x<-42; asS4(x, TRUE, c(1,2)) }"); + } + } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setseed.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setseed.java index 6b4512b2807a4861c1a47a30de6d6ee8af8ffb35..99ad536d7fe6b52f8627208a6f38b590cf633b64 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setseed.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setseed.java @@ -17,24 +17,26 @@ import com.oracle.truffle.r.test.TestBase; // Checkstyle: stop line length check public class TestBuiltin_setseed extends TestBase { + // Note: all the unimplemented tests fail on unimplemented RNG of given kind (2nd argument) + @Test public void testsetseed1() { - assertEval(Ignored.Unknown, "argv <- list(1000, 0L, NULL); .Internal(set.seed(argv[[1]], argv[[2]], argv[[3]]))"); + assertEval(Ignored.Unimplemented, "argv <- list(1000, 0L, NULL); .Internal(set.seed(argv[[1]], argv[[2]], argv[[3]]))"); } @Test public void testsetseed2() { - assertEval(Ignored.Unknown, "argv <- list(77, 2L, NULL); .Internal(set.seed(argv[[1]], argv[[2]], argv[[3]]))"); + assertEval(Ignored.Unimplemented, "argv <- list(77, 2L, NULL); .Internal(set.seed(argv[[1]], argv[[2]], argv[[3]]))"); } @Test public void testsetseed3() { - assertEval(Ignored.Unknown, "argv <- list(123, 6L, NULL); .Internal(set.seed(argv[[1]], argv[[2]], argv[[3]]))"); + assertEval(Ignored.Unimplemented, "argv <- list(123, 6L, NULL); .Internal(set.seed(argv[[1]], argv[[2]], argv[[3]]))"); } @Test public void testsetseed4() { - assertEval(Ignored.Unknown, "argv <- list(77, 4L, NULL); .Internal(set.seed(argv[[1]], argv[[2]], argv[[3]]))"); + assertEval(Ignored.Unimplemented, "argv <- list(77, 4L, NULL); .Internal(set.seed(argv[[1]], argv[[2]], argv[[3]]))"); } @Test @@ -49,11 +51,17 @@ public class TestBuiltin_setseed extends TestBase { @Test public void testsetseed7() { - assertEval(Ignored.Unknown, "argv <- list(123, 7L, NULL); .Internal(set.seed(argv[[1]], argv[[2]], argv[[3]]))"); + assertEval(Ignored.Unimplemented, "argv <- list(123, 7L, NULL); .Internal(set.seed(argv[[1]], argv[[2]], argv[[3]]))"); } @Test public void testsetseed8() { assertEval("argv <- list(NULL, NULL, NULL); .Internal(set.seed(argv[[1]], argv[[2]], argv[[3]]))"); } + + @Test + public void testArgCasts() { + assertEval(Output.IgnoreErrorMessage, "set.seed('hello world')"); + assertEval("set.seed(FALSE)"); + } } 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 be4d54917b58e99263457a838ff2253bd4ec83e0..6064dff03d221632c07e1c3dea90bb932de33a5a 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 @@ -127,4 +127,10 @@ public class TestBuiltin_shortRowNames extends TestBase { public void testshortRowNames23() { assertEval("argv <- list(structure(list(Df = c(NA, 1, 2), Deviance = c(12.2441566485997, 8.44399377410362, 11.9670615295804), AIC = c(73.9421143635373, 72.1419514890412, 77.665019244518)), .Names = c('Df', 'Deviance', 'AIC'), row.names = c('<none>', 'Temp', 'Soft'), class = c('anova', 'data.frame'), heading = c('Single term additions', '\\nModel:', 'cbind(X, M) ~ M.user')), 2L); .Internal(shortRowNames(argv[[1]], argv[[2]]))"); } + + @Test + public void testArgCasts() { + assertEval(Output.IgnoreErrorContext, ".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_signif.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_signif.java index d74e104144d1eb895d6cf5db85195a48bc4b6571..de5976c0fd0aab29a2d541fae97574869857b9de 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_signif.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_signif.java @@ -31,5 +31,19 @@ public class TestBuiltin_signif extends TestBase { assertEval("{ signif(0.555, 0) }"); assertEval("{ signif(0.555, -1) }"); assertEval("{ signif(0.0005551, 2) }"); + + assertEval("{ signif(42.1234, \"2\") }"); + assertEval("{ signif(42.1234, as.raw(2)) }"); + assertEval(Output.IgnoreErrorContext, "{ signif(42.1234, 42+7i) }"); + assertEval(Output.IgnoreErrorMessage, "{ signif(42.1234, character()) }"); + assertEval("{ signif(\"42.1234\", 2 }"); + + assertEval("{ signif(c(42.1234, 7.1234), 1:2) }"); + assertEval("{ signif(42.1234, 1:2) }"); + assertEval("{ signif(c(42.1234, 7.1234), 1) }"); + assertEval("{ signif(c(42.1234, 7.1234, 42.1234), c(1,2) }"); + assertEval("{ x<-42.1234; attr(x, \"foo\")<-\"foo\"; signif(x, 2) }"); + assertEval("{ x<-FALSE; attr(x, \"foo\")<-\"foo\"; signif(x, 2) }"); + assertEval("{ signif(42.1234, matrix(1:2, nrow=1)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sin.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sin.java index 6db2fce859e4a3c14794c41523e3d1796a1b1ee9..6a2d7e76bd248a24e00ffca929d7390f587c3b6c 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sin.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sin.java @@ -57,6 +57,6 @@ public class TestBuiltin_sin extends TestBase { assertEval("{ sin(1.2) }"); assertEval("{ sin(c(0.3,0.6,0.9)) }"); assertEval("{ sin() }"); - assertEval(Ignored.OutputFormatting, "{ sin(1+1i) }"); + assertEval("{ sin(1+1i) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sink.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sink.java index 7e759e85e00a60de1f1dcf7b30f4cda8631edd4f..31e19215b72c2789d28c7e4ac8783fcd89448a35 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sink.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sink.java @@ -19,11 +19,11 @@ public class TestBuiltin_sink extends TestBase { @Test public void testsink1() { - assertEval("argv <- list(structure(2L, class = c('terminal', 'connection')), FALSE, TRUE, FALSE); .Internal(sink(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))"); + assertEval(Ignored.SideEffects, "argv <- list(structure(2L, class = c('terminal', 'connection')), FALSE, FALSE, FALSE); .Internal(sink(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))"); } @Test public void testsink3() { - assertEval(Ignored.Unknown, "argv <- list(-1L, FALSE, FALSE, FALSE); .Internal(sink(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))"); + assertEval(Ignored.SideEffects, "argv <- list(-1L, FALSE, FALSE, FALSE); .Internal(sink(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))"); } } 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 227142fdd521b68034af8964878dc769c4cd584f..e3e5bf0fb2b5787bf1aca33248b5fdd7b763d345 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 @@ -120,4 +120,10 @@ public class TestBuiltin_sort extends TestBase { assertEval("{ sort(c(1L,10L,2L), method=\"quick\") }"); assertEval("{ sort(c(\"abc\", \"aba\", \"aa\")) }"); } + + @Test + public void testArgsCasts() { + assertEval("{ .Internal(sort(c(1L,10L,2L), 'not-numeric')) }"); + assertEval("{ .Internal(sort(c(1L,10L,2L), NULL)) }"); + } } 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 5b31458322853d4904ca93253dbf44312afb0f6e..c9b6ab146bd1d6dfa718c7a08fb23bd5826f9f97 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 @@ -97,8 +97,7 @@ public class TestBuiltin_strsplit extends TestBase { @Test public void teststrsplit16() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c('1', '2', '3', '4', '5', '1', '2', '3', '4', '5'), .Dim = 10L), '.', TRUE, FALSE, FALSE); .Internal(strsplit(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); + assertEval("argv <- list(structure(c('1', '2', '3', '4', '5', '1', '2', '3', '4', '5'), .Dim = 10L), '.', TRUE, FALSE, FALSE); .Internal(strsplit(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @Test @@ -112,8 +111,11 @@ public class TestBuiltin_strsplit extends TestBase { assertEval("{ strsplit(\"a,h,o,j\", split=\",\") }"); assertEval("{ strsplit(\"abc\", \".\", fixed = TRUE, perl=FALSE) }"); // Warning text formats differently - assertEval(Ignored.OutputFormatting, "{ strsplit(\"abc\", \".\", fixed = TRUE, perl=TRUE) }"); + assertEval(Output.IgnoreWarningContext, "{ strsplit(\"abc\", \".\", fixed = TRUE, perl=TRUE) }"); assertEval("{ strsplit(\"abc\", \".\", fixed = FALSE, perl=FALSE) }"); assertEval("{ strsplit(\"abc\", \".\", fixed = FALSE, perl=TRUE) }"); + + assertEval("{ .Internal(strsplit(7, \"42\", F, F, F)) }"); + assertEval("{ .Internal(strsplit(\"7\", 42, F, F, F)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strtoi.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strtoi.java index 716705d3dcf12e4f68f1130b97fe3324a2597551..b16c9f5067819a12e38ef10d313a145aaf993e95 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strtoi.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strtoi.java @@ -29,12 +29,12 @@ public class TestBuiltin_strtoi extends TestBase { @Test public void teststrtoi3() { - assertEval(Ignored.Unknown, "argv <- list(c('0xff', '077', '123'), 0L); .Internal(strtoi(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(c('0xff', '077', '123'), 0L); .Internal(strtoi(argv[[1]], argv[[2]]))"); } @Test public void teststrtoi4() { - assertEval(Ignored.Unknown, "argv <- list('1.3', 16L); .Internal(strtoi(argv[[1]], argv[[2]]))"); + assertEval("argv <- list('1.3', 16L); .Internal(strtoi(argv[[1]], argv[[2]]))"); } @Test 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 6c566f53a4cd418c70b1f9cf22aeb9019ebc992c..00fc2dc52149e953dff0057469a515912a4decb2 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 @@ -51,4 +51,10 @@ public class TestBuiltin_strtrim extends TestBase { public void teststrtrim8() { assertEval("argv <- list(character(0), 40L); .Internal(strtrim(argv[[1]], argv[[2]]))"); } + + @Test + public void teststrtrim() { + 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))"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sub.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sub.java index e596f3281b7f0e434236df30c6b2fa27422cda1b..1a6d875d9a3b5ef7e2081b0ecba6042601e96ac7 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sub.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sub.java @@ -141,5 +141,12 @@ public class TestBuiltin_sub extends TestBase { assertEval("{ sub('^([[:space:]]*).*$', '\\\\1', ' a45j%$ ') }"); assertEval("{ sub('^([[:upper:]]*).*$', '\\\\1', 'AASDFAa45j%$ ') }"); assertEval("{ sub('^([[:xdigit:]]*).*$', '\\\\1', '1234abABhxa45j%$ ') }"); + + assertEval("{ .Internal(sub(7, \"42\", \"7\", F, F, F, F)) }"); + assertEval("{ .Internal(sub(character(), \"42\", \"7\", F, F, F, F)) }"); + assertEval("{ .Internal(sub(\"7\", 42, \"7\", F, F, F, F)) }"); + assertEval("{ .Internal(sub(\"7\", character(), \"7\", F, F, F, F)) }"); + assertEval("{ .Internal(sub(\"7\", \"42\", 7, F, F, F, F)) }"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_parentasis_dataframe.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_subset_dataframe.java similarity index 96% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_parentasis_dataframe.java rename to com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_subset_dataframe.java index 008b64f6e626b3a124465028c070bb27dda791a7..c3fb5f95da3ea1964cd6e627bb386d8dbf8d67e4 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_parentasis_dataframe.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_subset_dataframe.java @@ -16,18 +16,18 @@ import com.oracle.truffle.r.test.TestBase; // Checkstyle: stop line length check -public class TestBuiltin_extract_parentasis_dataframe extends TestBase { +public class TestBuiltin_subset_dataframe extends TestBase { @Test - public void testextract_parentasis_dataframe1() { - assertEval(Ignored.Unknown, + public void testsubset_dataframe1() { + assertEval(Output.IgnoreWarningContext, "argv <- structure(list(x = structure(list(ID = c(13, 41, 121, 202, 247, 292, 415, 492), Location = c(0.15998329123474, 0.533277637449134, 1.5998329123474, 2.6797201281819, 3.27965747031217, 3.87959481244245, 5.51942354759854, 6.54598299968812), Peak_Value = c(0.997547264684804, 0.949162789397664, 0.990440013891923, 0.973478735915337, 0.93861267739627, 0.957347289323235, 0.924803043529451, 0.968307855031101)), .Names = c('ID', 'Location', 'Peak_Value'), row.names = c(NA, -8L), class = 'data.frame'), i = 2), .Names = c('x', 'i'));" + "do.call('[.data.frame', argv)"); } @Test - public void testextract_parentasis_dataframe2() { - assertEval(Ignored.Unknown, + public void testsubset_dataframe2() { + assertEval(Output.IgnoreWarningContext, "argv <- structure(list(x = structure(list(Satellites = c(8L, 0L, 9L, 0L, 4L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 11L, 0L, 14L, 8L, 1L, 1L, 0L, 5L, 4L, 3L, 1L, 2L, 3L, 0L, 3L, 5L, 0L, 0L, 4L, 0L, 0L, 8L, 5L, 0L, 0L, 6L, 0L, 6L, 3L, 5L, 6L, 5L, 9L, 4L, 6L, 4L, 3L, 3L, 5L, 5L, 6L, 4L, 5L, 15L, 3L, 3L, 0L, 0L, 0L, 5L, 3L, 5L, 1L, 8L, 10L, 0L, 0L, 3L, 7L, 1L, 0L, 6L, 0L, 0L, 3L, 4L, 0L, 5L, 0L, 0L, 0L, 4L, 0L, 3L, 0L, 0L, 0L, 0L, 5L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 4L, 1L, 1L, 1L, 1L, 2L, 4L, 3L, 6L, 0L, 2L, 2L, 0L, 12L, 0L, 5L, 6L, 6L, 2L, 0L, 2L, 3L, 0L, 3L, 4L, 2L, 6L, 6L, 0L, 4L, 10L, 7L, 0L, 5L, 5L, 6L, 6L, 7L, 3L, 3L, 0L, 0L, 8L, 4L, 4L, 10L, 9L, 4L, 0L, 0L, 0L, 0L, 4L, 0L, 2L, 0L, 4L, 4L, 3L, 8L, 0L, 7L, 0L, 0L, 2L, 3L, 4L, 0L, 0L, 0L), Width = c(28.3, 22.5, 26, 24.8, 26, 23.8, 26.5, 24.7, 23.7, 25.6, 24.3, 25.8, 28.2, 21, 26, 27.1, 25.2, 29, 24.7, 27.4, 23.2, 25, 22.5, 26.7, 25.8, 26.2, 28.7, 26.8, 27.5, 24.9, 29.3, 25.8, 25.7, 25.7, 26.7, 23.7, 26.8, 27.5, 23.4, 27.9, 27.5, 26.1, 27.7, 30, 28.5, 28.9, 28.2, 25, 28.5, 30.3, 24.7, 27.7, 27.4, 22.9, 25.7, 28.3, 27.2, 26.2, 27.8, 25.5, 27.1, 24.5, 27, 26, 28, 30, 29, 26.2, 26.5, 26.2, 25.6, 23, 23, 25.4, 24.2, 22.9, 26, 25.4, 25.7, 25.1, 24.5, 27.5, 23.1, 25.9, 25.8, 27, 28.5, 25.5, 23.5, 24, 29.7, 26.8, 26.7, 28.7, 23.1, 29, 25.5, 26.5, 24.5, 28.5, 28.2, 24.5, 27.5, 24.7, 25.2, 27.3, 26.3, 29, 25.3, 26.5, 27.8, 27, 25.7, 25, 31.9, 23.7, 29.3, 22, 25, 27, 23.8, 30.2, 26.2, 24.2, 27.4, 25.4, 28.4, 22.5, 26.2, 24.9, 24.5, 25.1, 28, 25.8, 27.9, 24.9, 28.4, 27.2, 25, 27.5, 33.5, 30.5, 29, 24.3, 25.8, 25, 31.7, 29.5, 24, 30, 27.6, 26.2, 23.1, 22.9, 24.5, 24.7, 28.3, 23.9, 23.8, 29.8, 26.5, 26, 28.2, 25.7, 26.5, 25.8, 24.1, 26.2, 26.1, 29, 28, 27, 24.5), Dark = structure(c(1L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 1L), .Label = c('no', 'yes'), class = 'factor'), GoodSpine = structure(c(1L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L), .Label = c('no', 'yes'), class = 'factor'), Rep1 = c(2, 4, 5, 6, 6, 8, 9, 9, 10, 10, 11, 11, 13, 15, 15, 15, 15, 15, 17, 18, 19, 19, 19, 20, 20, 21, 21, 22, 23, 25, 25, 26, 27, 27, 28, 29, 29, 31, 33, 33, 36, 39, 40, 40, 41, 42, 43, 44, 45, 45, 49, 50, 51, 53, 55, 55, 56, 56, 56, 58, 59, 59, 60, 60, 62, 63, 64, 64, 64, 65, 66, 66, 67, 68, 70, 70, 71, 74, 75, 76, 76, 77, 79, 79, 79, 80, 80, 81, 82, 83, 83, 84, 87, 88, 88, 91, 92, 95, 97, 97, 97, 98, 98, 99, 100, 100, 101, 101, 103, 103, 103, 106, 107, 107, 111, 112, 112, 113, 113, 116, 116, 117, 117, 120, 122, 122, 122, 124, 125, 126, 127, 128, 128, 129, 130, 131, 133, 134, 134, 135, 141, 144, 146, 147, 147, 153, 153, 154, 154, 155, 155, 155, 156, 157, 157, 161, 163, 163, 164, 164, 164, 165, 167, 168, 168, 169, 170, 170, 170, 171, 171, 173, 173), Rep2 = c(2, 5, 6, 6, 8, 8, 9, 11, 12, 13, 13, 15, 15, 15, 16, 17, 17, 18, 19, 20, 23, 24, 24, 24, 25, 25, 26, 26, 27, 28, 29, 30, 30, 32, 33, 34, 38, 39, 39, 41, 42, 47, 48, 49, 49, 51, 54, 55, 55, 56, 57, 59, 59, 62, 63, 65, 67, 68, 69, 69, 70, 73, 75, 76, 76, 77, 78, 79, 81, 82, 83, 84, 85, 85, 85, 86, 87, 88, 89, 91, 92, 92, 92, 92, 96, 98, 98, 99, 100, 101, 101, 102, 103, 104, 104, 104, 105, 107, 107, 107, 108, 109, 109, 110, 111, 111, 111, 112, 112, 112, 113, 113, 115, 116, 117, 120, 122, 123, 123, 124, 124, 125, 125, 126, 128, 130, 131, 131, 131, 131, 132, 133, 133, 134, 134, 136, 137, 138, 139, 139, 141, 143, 144, 144, 145, 145, 150, 150, 150, 152, 152, 153, 154, 155, 155, 156, 157, 157, 158, 159, 160, 161, 163, 163, 166, 167, 169, 170, 172, 173, 173, 173, 173)), .Names = c('Satellites', 'Width', 'Dark', 'GoodSpine', 'Rep1', 'Rep2'), row.names = c(NA, -173L), class = 'data.frame'), i = c(2, 4, 5, 6, 6, 8, 9, 9, 10, 10, 11, 11, 13, 15, 15, 15, 15, 15, 17, 18, 19, 19, 19, 20, 20, 21, 21, 22, 23, 25, 25, 26, 27, 27, 28, 29, 29, 31, 33, 33, 36, 39, 40, 40, 41, 42, 43, 44, 45, 45, 49, 50, 51, 53, 55, 55, 56, 56, 56, 58, 59, 59, 60, 60, 62, 63, 64, 64, 64, 65, 66, 66, 67, 68, 70, 70, 71, 74, 75, 76, 76, 77, 79, 79, 79, 80, 80, 81, 82, 83, 83, 84, 87, 88, 88, 91, 92, 95, 97, 97, 97, 98, 98, 99, 100, 100, 101, 101, 103, 103, 103, 106, 107, 107, 111, 112, 112, 113, 113, 116, 116, 117, 117, 120, 122, 122, 122, 124, 125, 126, 127, 128, 128, 129, 130, 131, 133, 134, 134, 135, 141, 144, 146, 147, 147, 153, 153, 154, 154, 155, 155, 155, 156, 157, 157, 161, 163, 163, 164, 164, 164, 165, 167, 168, 168, 169, 170, 170, 170, 171, 171, 173, 173), j = c(-5L, -6L)), .Names = c('x', 'i', 'j'));" + "do.call('[.data.frame', argv)"); } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sweep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sweep.java index 0053dda72df7dfcc34a63da24a56f8f9732ca04d..f3f28eb9901d0e5c3e4d8095a63329ce6fbd9549 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sweep.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sweep.java @@ -35,7 +35,5 @@ public class TestBuiltin_sweep extends TestBase { // Correct output but warnings assertEval(Ignored.Unknown, "{ A <- matrix(1:50, nrow=4); sweep(A, 1, 5, '-') }"); assertEval(Ignored.Unknown, "{ A <- matrix(7:1, nrow=5); sweep(A, 1, -1, '*') }"); - - assertEval("{rowMeans(matrix(c(NaN,4+5i,2+0i,5+10i),nrow=2,ncol=2), na.rm = FALSE)}"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java index 3d851f24c7e6da980f8521ef2ff438e066cf4420..693cde32eb6e252583908b569377a1a8b142a8c2 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java @@ -40,5 +40,11 @@ public class TestBuiltin_t extends TestBase { assertEval("{ t(t(matrix(1:4, nrow=2))) }"); assertEval("{ x<-matrix(1:2, ncol=2, dimnames=list(\"a\", c(\"b\", \"c\"))); t(x) }"); + + assertEval("t(new.env())"); + assertEval("v <- as.complex(1:50); dim(v) <- c(5,10); dimnames(v) <- list(as.character(40:44), as.character(10:19)); t(v)"); + assertEval("t(1)"); + assertEval("t(TRUE)"); + assertEval("t(as.raw(c(1,2,3,4)))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tabulate.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tabulate.java index 8e671d9096a3f72dd6eb57dcbe0876ed17e38e5f..edfddef077b82650e2074d6bc75fb1cadb887773 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tabulate.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tabulate.java @@ -59,5 +59,11 @@ public class TestBuiltin_tabulate extends TestBase { assertEval("{tabulate(c(-2,0,2,3,3,5))}"); assertEval("{tabulate(c(-2,0,2,3,3,5), nbins = 3)}"); assertEval("{tabulate(factor(letters[1:10]))}"); + + assertEval("{ .Internal(tabulate(c(2,3,5), 7)) }"); + assertEval("{ .Internal(tabulate(c(2L,3L,5L), c(7, 42))) }"); + assertEval("{ .Internal(tabulate(c(2L,3L,5L), integer())) }"); + assertEval("{ .Internal(tabulate(c(2L,3L,5L), -1)) }"); + assertEval("{ .Internal(tabulate(c(2L,3L,5L), NA)) }"); } } 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 7ba058c0bb41bbfb98ca8cf3e0bf115de331587f..6d1687f6aa98c20989125c44c677ebbdf332e29e 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 @@ -19,69 +19,62 @@ public class TestBuiltin_tdefault extends TestBase { @Test public void testtdefault1() { - assertEval(Ignored.Unknown, "argv <- list(structure(c('D:', 'E:', 'F:', 'G:'), .Dim = c(4L, 1L))); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(c('D:', 'E:', 'F:', 'G:'), .Dim = c(4L, 1L))); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault2() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0.63, -0.37, 0.4, -0.6, 0.85, -0.05, 1.02, -1.76, -1.62, -0.46, -0.57, 1.41, 0, -0.65, 0.57, -0.29, 1.22, 0.8, -0.5, 0.44, 1.63, -0.13, 0.17, 1.02, 0.11), .Dim = c(5L, 5L))); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(c(0.63, -0.37, 0.4, -0.6, 0.85, -0.05, 1.02, -1.76, -1.62, -0.46, -0.57, 1.41, 0, -0.65, 0.57, -0.29, 1.22, 0.8, -0.5, 0.44, 1.63, -0.13, 0.17, 1.02, 0.11), .Dim = c(5L, 5L))); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault3() { - assertEval(Ignored.Unknown, "argv <- list(structure(NA, .Dim = c(1L, 1L))); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(NA, .Dim = c(1L, 1L))); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault4() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0, 0, -0.51, 0, 0, 0, 0.18, -0.15, 0, 2.62, -2.77555756156289e-16, 0, 8.26162055433954e-17, 0.560000000000001, 0, 0, 0, 0, 0, 0, 1.79, 0, 0.05, 0, 0, 0, 0, 0, 0, -0.18, -1.47, 0, -5.55111512312578e-17, 0, 0, 0.23, 0, 2.206351421008e-17, -2.12, 0), .Dim = c(5L, 8L))); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(c(0, 0, -0.51, 0, 0, 0, 0.18, -0.15, 0, 2.62, -2.77555756156289e-16, 0, 8.26162055433954e-17, 0.560000000000001, 0, 0, 0, 0, 0, 0, 1.79, 0, 0.05, 0, 0, 0, 0, 0, 0, -0.18, -1.47, 0, -5.55111512312578e-17, 0, 0, 0.23, 0, 2.206351421008e-17, -2.12, 0), .Dim = c(5L, 8L))); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault5() { - assertEval(Ignored.Unknown, "argv <- list(structure(c(NA, 0, NA, 0, NA, 0, NA, 0, NA, 0, NA, 0, NA, 0, NA, 0), .Dim = c(4L, 4L))); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(c(NA, 0, NA, 0, NA, 0, NA, 0, NA, 0, NA, 0, NA, 0, NA, 0), .Dim = c(4L, 4L))); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault6() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0, 10975969, 8779369, 10080625, 11148921, 7628644, 10732176, 6812100, 20115225, 8862529, 9180900, 20539024, 7579009, 15594601, 8208225, 5207524, 4748041, 9e+06, 667489, 15421329, 3964081, 0, 0, 1737124, 1758276, 1674436, 2244004, 4919524, 644809, 1373584, 4072324, 2220100, 1703025, 416025, 404496, 271441, 1028196, 1863225, 1067089, 2131600, 8225424, 3247204, 0, 0, 0, 41616, 339889, 42436, 933156, 458329, 5089536, 356409, 29584, 4343056, 476100, 2427364, 1022121, 855625, 558009, 81225, 2283121, 2611456, 1380625, 0, 0, 0, 0, 211600, 167281, 1290496, 558009, 4946176, 509796, 108900, 4210704, 546121, 2402500, 1121481, 1159929, 954529, 78400, 2762244, 3189796, 1907161, 0, 0, 0, 0, 0, 616225, 2387025, 727609, 4190209, 1243225, 534361, 3337929, 622521, 1814409, 1212201, 1461681, 1345600, 115600, 3218436, 4822416, 2521744, 0, 0, 0, 0, 0, 0, 577600, 2762244, 5934096, 211600, 72361, 5244100, 509796, 3111696, 1071225, 829921, 339889, 216225, 2241009, 1968409, 877969, 0, 0, 0, 0, 0, 0, 0, 2010724, 10214416, 211600, 72361, 8826841, 2125764, 6240004, 3161284, 2362369, 1218816, 1382976, 4202500, 422500, 2117025, 0, 0, 0, 0, 0, 0, 0, 0, 3900625, 1249924, 801025, 3748096, 24964, 2070721, 180625, 107584, 349281, 263169, 990025, 4276624, 1038361, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8392609, 5895184, 456976, 3301489, 487204, 2866249, 4774225, 6579225, 3884841, 6922161, 15100996, 8844676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 302500, 7134241, 1343281, 4831204, 2187441, 1532644, 648025, 769129, 3066001, 900601, 1334025, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5198400, 744769, 2992900, 1399489, 1205604, 724201, 208849, 2832489, 2250000, 1452025, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1387684, 446224, 3104644, 5062500, 6285049, 3236401, 7290000, 10439361, 8625969, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1640961, 102400, 107584, 524176, 221841, 1098304, 4443664, 1338649, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1338649, 2972176, 4040100, 1620529, 4397409, 10163344, 5803281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 381924, 1229881, 627264, 1022121, 5895184, 1857769, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109561, 732736, 343396, 4782969, 806404, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 674041, 894916, 3076516, 183184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2178576, 3337929, 1560001, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7327849, 1461681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4431025, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), .Dim = c(21L, 21L))); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(c(0, 10975969, 8779369, 10080625, 11148921, 7628644, 10732176, 6812100, 20115225, 8862529, 9180900, 20539024, 7579009, 15594601, 8208225, 5207524, 4748041, 9e+06, 667489, 15421329, 3964081, 0, 0, 1737124, 1758276, 1674436, 2244004, 4919524, 644809, 1373584, 4072324, 2220100, 1703025, 416025, 404496, 271441, 1028196, 1863225, 1067089, 2131600, 8225424, 3247204, 0, 0, 0, 41616, 339889, 42436, 933156, 458329, 5089536, 356409, 29584, 4343056, 476100, 2427364, 1022121, 855625, 558009, 81225, 2283121, 2611456, 1380625, 0, 0, 0, 0, 211600, 167281, 1290496, 558009, 4946176, 509796, 108900, 4210704, 546121, 2402500, 1121481, 1159929, 954529, 78400, 2762244, 3189796, 1907161, 0, 0, 0, 0, 0, 616225, 2387025, 727609, 4190209, 1243225, 534361, 3337929, 622521, 1814409, 1212201, 1461681, 1345600, 115600, 3218436, 4822416, 2521744, 0, 0, 0, 0, 0, 0, 577600, 2762244, 5934096, 211600, 72361, 5244100, 509796, 3111696, 1071225, 829921, 339889, 216225, 2241009, 1968409, 877969, 0, 0, 0, 0, 0, 0, 0, 2010724, 10214416, 211600, 72361, 8826841, 2125764, 6240004, 3161284, 2362369, 1218816, 1382976, 4202500, 422500, 2117025, 0, 0, 0, 0, 0, 0, 0, 0, 3900625, 1249924, 801025, 3748096, 24964, 2070721, 180625, 107584, 349281, 263169, 990025, 4276624, 1038361, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8392609, 5895184, 456976, 3301489, 487204, 2866249, 4774225, 6579225, 3884841, 6922161, 15100996, 8844676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 302500, 7134241, 1343281, 4831204, 2187441, 1532644, 648025, 769129, 3066001, 900601, 1334025, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5198400, 744769, 2992900, 1399489, 1205604, 724201, 208849, 2832489, 2250000, 1452025, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1387684, 446224, 3104644, 5062500, 6285049, 3236401, 7290000, 10439361, 8625969, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1640961, 102400, 107584, 524176, 221841, 1098304, 4443664, 1338649, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1338649, 2972176, 4040100, 1620529, 4397409, 10163344, 5803281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 381924, 1229881, 627264, 1022121, 5895184, 1857769, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109561, 732736, 343396, 4782969, 806404, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 674041, 894916, 3076516, 183184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2178576, 3337929, 1560001, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7327849, 1461681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4431025, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), .Dim = c(21L, 21L))); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault7() { - assertEval(Ignored.Unknown, "argv <- list(structure(logical(0), .Dim = c(0L, 0L))); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(logical(0), .Dim = c(0L, 0L))); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault8() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE), .Dim = c(4L, 4L), .Dimnames = list(NULL, NULL))); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE), .Dim = c(4L, 4L), .Dimnames = list(NULL, NULL))); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault9() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0.589872882227945+0i, 0.193623477236295+0i, 0.66266867945261+0i, 0.140441698505598+0i, -0.394596353845825+0i, 0.168331537203598+0i, 0.293129347035038+0i, -0.481237717889449+0i, 0.7985227152757+0i, -0.128496737541326+0i, -0.0231518691888815+0i, -0.892171028872675+0i, 0.158252886617681+0i, 0.418477841524233+0i, -0.0576815934568704+0i, 0.471807942431513+0i, -0.00978429568549377+0i, 0.0825499722933953+0i, 0.0943143868799564+0i, 0.872692289136496+0i, -0.632910525118973+0i, 0.283760916561723+0i, 0.545364104158516+0i, 0.398269626120626+0i, 0.25072556357658+0i), .Dim = c(5L, 5L))); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(c(0.589872882227945+0i, 0.193623477236295+0i, 0.66266867945261+0i, 0.140441698505598+0i, -0.394596353845825+0i, 0.168331537203598+0i, 0.293129347035038+0i, -0.481237717889449+0i, 0.7985227152757+0i, -0.128496737541326+0i, -0.0231518691888815+0i, -0.892171028872675+0i, 0.158252886617681+0i, 0.418477841524233+0i, -0.0576815934568704+0i, 0.471807942431513+0i, -0.00978429568549377+0i, 0.0825499722933953+0i, 0.0943143868799564+0i, 0.872692289136496+0i, -0.632910525118973+0i, 0.283760916561723+0i, 0.545364104158516+0i, 0.398269626120626+0i, 0.25072556357658+0i), .Dim = c(5L, 5L))); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault10() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 74, 68, 56, 57, 60, 74, 53, 61, 57, 57, 67, 70, 63, 57, 67, 50, 58, 72, 60, 70, 53, 74, 73, 48, 61, 65, 74, 70, 68, 74, 63, 74, 63, 68, 58, 59, 62, 57, 48, 73, 69, 68, 68, 67, 63, 74, 40, 81, 73, 59, 55, 42, 44, 71, 61, 72, 63, 70, 66, 72, 69, 71, 64, 56, 63, 59, 66, 67, 55, 69, 44, 80, 76, 49, 68, 66, 80, 75, 72, 70, 66, 50, 64, 53, 47, 67, 56, 54, 56, 74, 76, 57, 71, 54, 82, 70, 60, 55, 69, 62, 63, 69, 63, 64, 46, 61, 65, 61, 56, 53, 56, 60, 39, 58, 64, 53, 72, 52, 50, 64, 71, 70, 64, 60, 73, 62, 69, 67, 69, 65, 65, 76, 67, 76, 77, 39, 66, 1, 0, 0, 1, 0, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 0, 0, 0, 3, 1, 2, 2, 2, 2, 2, 2, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 2, 1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 0, 0, 1, 1, 1, 1, 0, 2, 0, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 1, 1, 2, 2, 2, 2, 1, 0, 2, 0, 1, 1, 1, 1, 0, 0, 2, 1, 0, 1, 2, 1, 0, 1, 0, 1, 0, 2, 2, 2, 1, 2, 1, 1, 0, 1, 0, 1, 1, 1, 2, 0, 0, 0, 1, 0, 1, 2, 1, 1, 1, 0, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 1), .Dim = c(137L, 3L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '9', '10', '11', '15', '16', '17', '18', '20', '21', '23', '24', '25', '27', '28', '29', '30', '32', '33', '35', '37', '39', '41', '45', '47', '48', '49', '52', '53', '54', '55', '56', '58', '62', '63', '65', '66', '69', '70', '71', '73', '74', '79', '80', '81', '82', '83', '85', '86', '88', '90', '91', '92', '93', '96', '97', '98', '99', '103', '104', '105', '106', '108', '109', '111', '112', '113', '116', '117', '118', '119', '120', '121', '124', '125', '126', '127', '128', '132', '133', '135', '138', '139', '140', '142', '143', '145', '147', '148', '149', '151', '152', '155', '156', '158', '159', '163', '164', '165', '168', '169', '170', '171', '173', '175', '177', '181', '182', '188', '189', '190', '191', '192', '193', '194', '195', '196', '198', '200', '202', '206', '209', '212', '213', '215', '216', '218', '221', '223', '224', '225', '227'), c('(Intercept)', 'age', 'ph.ecog')), assign = 0:2)); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 74, 68, 56, 57, 60, 74, 53, 61, 57, 57, 67, 70, 63, 57, 67, 50, 58, 72, 60, 70, 53, 74, 73, 48, 61, 65, 74, 70, 68, 74, 63, 74, 63, 68, 58, 59, 62, 57, 48, 73, 69, 68, 68, 67, 63, 74, 40, 81, 73, 59, 55, 42, 44, 71, 61, 72, 63, 70, 66, 72, 69, 71, 64, 56, 63, 59, 66, 67, 55, 69, 44, 80, 76, 49, 68, 66, 80, 75, 72, 70, 66, 50, 64, 53, 47, 67, 56, 54, 56, 74, 76, 57, 71, 54, 82, 70, 60, 55, 69, 62, 63, 69, 63, 64, 46, 61, 65, 61, 56, 53, 56, 60, 39, 58, 64, 53, 72, 52, 50, 64, 71, 70, 64, 60, 73, 62, 69, 67, 69, 65, 65, 76, 67, 76, 77, 39, 66, 1, 0, 0, 1, 0, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 0, 0, 0, 3, 1, 2, 2, 2, 2, 2, 2, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 2, 1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 0, 0, 1, 1, 1, 1, 0, 2, 0, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 1, 1, 2, 2, 2, 2, 1, 0, 2, 0, 1, 1, 1, 1, 0, 0, 2, 1, 0, 1, 2, 1, 0, 1, 0, 1, 0, 2, 2, 2, 1, 2, 1, 1, 0, 1, 0, 1, 1, 1, 2, 0, 0, 0, 1, 0, 1, 2, 1, 1, 1, 0, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 1), .Dim = c(137L, 3L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '9', '10', '11', '15', '16', '17', '18', '20', '21', '23', '24', '25', '27', '28', '29', '30', '32', '33', '35', '37', '39', '41', '45', '47', '48', '49', '52', '53', '54', '55', '56', '58', '62', '63', '65', '66', '69', '70', '71', '73', '74', '79', '80', '81', '82', '83', '85', '86', '88', '90', '91', '92', '93', '96', '97', '98', '99', '103', '104', '105', '106', '108', '109', '111', '112', '113', '116', '117', '118', '119', '120', '121', '124', '125', '126', '127', '128', '132', '133', '135', '138', '139', '140', '142', '143', '145', '147', '148', '149', '151', '152', '155', '156', '158', '159', '163', '164', '165', '168', '169', '170', '171', '173', '175', '177', '181', '182', '188', '189', '190', '191', '192', '193', '194', '195', '196', '198', '200', '202', '206', '209', '212', '213', '215', '216', '218', '221', '223', '224', '225', '227'), c('(Intercept)', 'age', 'ph.ecog')), assign = 0:2)); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault11() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), .Dim = c(20L, 20L), .Dimnames = list(c(NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_), c(NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_)))); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(c(NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), .Dim = c(20L, 20L), .Dimnames = list(c(NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_), c(NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_)))); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault12() { - assertEval(Ignored.Unknown, "argv <- list(structure('foo', .Dim = c(1L, 1L), .Dimnames = list(structure('object', simpleOnly = TRUE), NULL))); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure('foo', .Dim = c(1L, 1L), .Dimnames = list(structure('object', simpleOnly = TRUE), NULL))); .Internal(t.default(argv[[1]]))"); } @Test @@ -97,54 +90,52 @@ public class TestBuiltin_tdefault extends TestBase { @Test public void testtdefault15() { - assertEval(Ignored.Unknown, "argv <- list(structure(list(3, 3, 3, 3, 3, 'fred'), .Dim = 2:3)); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(list(3, 3, 3, 3, 3, 'fred'), .Dim = 2:3)); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault16() { - assertEval(Ignored.Unknown, "argv <- list(1.28578345790245); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(1.28578345790245); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault17() { - 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))); .Internal(t.default(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))); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault18() { - assertEval(Ignored.Unknown, "argv <- list(structure(c(0, 1954.88214285714, 557.144827586207, 0, 0, 1392.34285714286, 0, 0, 0), .Dim = c(3L, 3L))); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(c(0, 1954.88214285714, 557.144827586207, 0, 0, 1392.34285714286, 0, 0, 0), .Dim = c(3L, 3L))); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault19() { - assertEval(Ignored.Unknown, "argv <- list(c(3, 4)); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(c(3, 4)); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault20() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 1L, 1L), .Dim = c(4L, 4L), .Dimnames = list(c('Y', 'B', 'V', 'N'), c('B', 'V', 'N', 'V:N')))); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(c(0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 1L, 1L), .Dim = c(4L, 4L), .Dimnames = list(c('Y', 'B', 'V', 'N'), c('B', 'V', 'N', 'V:N')))); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault21() { - assertEval(Ignored.Unknown, "argv <- list(-3:5); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(-3:5); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault22() { - assertEval(Ignored.Unknown, + assertEval( "argv <- list(structure(c(8.3, 8.6, 8.8, 10.5, 10.7, 10.8, 11, 11, 11.1, 11.2, 11.3, 11.4, 11.4, 11.7, 12, 12.9, 12.9, 13.3, 13.7, 13.8, 14, 14.2, 14.5, 16, 16.3, 17.3, 17.5, 17.9, 18, 18, 20.6, 70, 65, 63, 72, 81, 83, 66, 75, 80, 75, 79, 76, 76, 69, 75, 74, 85, 86, 71, 64, 78, 80, 74, 72, 77, 81, 82, 80, 80, 80, 87, 10.3, 10.3, 10.2, 16.4, 18.8, 19.7, 15.6, 18.2, 22.6, 19.9, 24.2, 21, 21.4, 21.3, 19.1, 22.2, 33.8, 27.4, 25.7, 24.9, 34.5, 31.7, 36.3, 38.3, 42.6, 55.4, 55.7, 58.3, 51.5, 51, 77), .Dim = c(31L, 3L), .Dimnames = list(NULL, c('Girth', 'Height', 'Volume')))); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault23() { - assertEval(Ignored.Unknown, "argv <- list(structure(list(), .Dim = 0L)); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(list(), .Dim = 0L)); .Internal(t.default(argv[[1]]))"); } @Test public void testtdefault24() { - assertEval(Ignored.Unknown, "argv <- list(structure('Seed', .Dim = c(1L, 1L))); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure('Seed', .Dim = c(1L, 1L))); .Internal(t.default(argv[[1]]))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tempfile.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tempfile.java new file mode 100644 index 0000000000000000000000000000000000000000..b0b796a6c6a6b8f6c85d28edfe277641af9cc528 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tempfile.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, 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.test.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +// Checkstyle: stop line length check +public class TestBuiltin_tempfile extends TestBase { + + @Test + public void testTempfile() { + // checking error messages; other tests not possible due to random nature of the builtin + assertEval("{ tempfile(42) }"); + assertEval("{ tempfile(integer()) }"); + assertEval("{ tempfile(character()) }"); + assertEval("{ tempfile(\"file\", 42) }"); + assertEval("{ tempfile(\"file\", character()) }"); + assertEval("{ tempfile(\"file\", integer()) }"); + assertEval("{ tempfile(\"file\", tempdir(), 42) }"); + assertEval("{ tempfile(\"file\", tempdir(), integer()) }"); + assertEval("{ tempfile(\"file\", tempdir(), character()) }"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tolower.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tolower.java index 8b0588b2bdd7b3dbe88f9dcc5db85d1dbc65c20f..f216fb17383d13f45e41e65f7a756002c2cc96a6 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tolower.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tolower.java @@ -39,7 +39,7 @@ public class TestBuiltin_tolower extends TestBase { @Test public void testtolower5() { - assertEval(Ignored.Unimplemented, "argv <- list(structure('base', .Names = 'Priority')); .Internal(tolower(argv[[1]]))"); + assertEval("argv <- list(structure('base', .Names = 'Priority')); .Internal(tolower(argv[[1]]))"); } @Test @@ -57,8 +57,9 @@ public class TestBuiltin_tolower extends TestBase { assertEval("{ tolower(c(\"Hello\",\"ByE\")) }"); assertEval("{ tolower(c()) }"); + // double-to-string conversion problem assertEval(Ignored.OutputFormatting, "{ tolower(1E100) }"); - assertEval(Ignored.Unimplemented, "{ tolower(c(a=\"HI\", \"HELlo\")) }"); + assertEval("{ tolower(c(a=\"HI\", \"HELlo\")) }"); assertEval("{ tolower(NA) }"); assertEval("tolower(c('NA', 'na'))"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_toupper.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_toupper.java index d00b82523eba4d16051e8f3682407f4e391229be..a6a2008deac27591833cea3559e7b408bbcffd1f 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_toupper.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_toupper.java @@ -34,8 +34,7 @@ public class TestBuiltin_toupper extends TestBase { @Test public void testtoupper4() { - assertEval(Ignored.Unimplemented, - "argv <- list(structure(c('BasicClasses', 'Classes', 'Documentation', 'environment-class', 'GenericFunctions', 'language-class', 'LinearMethodsList-class', 'MethodDefinition-class', 'MethodWithNext-class', 'Methods', 'MethodsList-class', 'callNextMethod', 'ObjectsWithPackage-class', 'S3Part', 'S4groupGeneric', 'SClassExtension-class', 'StructureClasses', 'TraceClasses', 'as', 'callGeneric', 'canCoerce', 'cbind2', 'className', 'classRepresentation-class', 'classesToAM', 'dotsMethods', 'evalSource', 'findClass', 'findMethods', 'fixPre1.8', 'genericFunction-class', 'getClass', 'getMethod', 'getPackageName', 'hasArg', 'implicitGeneric', 'inheritedSlotNames', 'initialize-methods', 'is', 'isSealedMethod', 'LocalReferenceClasses', 'method.skeleton', 'new', 'nonStructure-class', 'promptClass', 'promptMethods', 'ReferenceClasses', 'representation', 'selectSuperClasses', 'setClass', 'setClassUnion', 'setGeneric', 'setLoadActions', 'setMethod', 'setOldClass', 'makeClassRepresentation', 'show', 'showMethods', 'signature-class', 'slot', 'envRefClass-class', 'testInheritedMethods', 'validObject', '.BasicFunsList'), .Names = c('/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/BasicClasses.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/Classes.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/Documentation.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/EnvironmentClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/GenericFunctions.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/LanguageClasses.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/LinearMethodsList-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/MethodDefinition-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/MethodWithNext-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/Methods.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/MethodsList-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/NextMethod.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/ObjectsWithPackage-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/S3Part.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/S4groupGeneric.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/SClassExtension-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/StructureClasses.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/TraceClasses.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/as.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/callGeneric.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/canCoerce.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/cbind2.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/className.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/classRepresentation-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/classesToAM.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/dotsMethods.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/evalSource.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/findClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/findMethods.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/fixPrevious.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/genericFunction-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/getClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/getMethod.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/getPackageName.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/hasArg.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/implicitGeneric.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/inheritedSlotNames.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/initialize-methods.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/is.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/isSealedMethod.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/localRefClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/method.skeleton.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/new.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/nonStructure-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/promptClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/promptMethods.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/refClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/representation.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/selectSuperClasses.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/setClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/setClassUnion.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/setGeneric.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/setLoadActions.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/setMethod.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/setOldClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/setSClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/show.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/showMethods.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/signature-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/slot.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/stdRefClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/testInheritedMethods.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/validObject.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/zBasicFunsList.tex'))); .Internal(toupper(argv[[1]]))"); + assertEval("argv <- list(structure(c('BasicClasses', 'Classes', 'Documentation', 'environment-class', 'GenericFunctions', 'language-class', 'LinearMethodsList-class', 'MethodDefinition-class', 'MethodWithNext-class', 'Methods', 'MethodsList-class', 'callNextMethod', 'ObjectsWithPackage-class', 'S3Part', 'S4groupGeneric', 'SClassExtension-class', 'StructureClasses', 'TraceClasses', 'as', 'callGeneric', 'canCoerce', 'cbind2', 'className', 'classRepresentation-class', 'classesToAM', 'dotsMethods', 'evalSource', 'findClass', 'findMethods', 'fixPre1.8', 'genericFunction-class', 'getClass', 'getMethod', 'getPackageName', 'hasArg', 'implicitGeneric', 'inheritedSlotNames', 'initialize-methods', 'is', 'isSealedMethod', 'LocalReferenceClasses', 'method.skeleton', 'new', 'nonStructure-class', 'promptClass', 'promptMethods', 'ReferenceClasses', 'representation', 'selectSuperClasses', 'setClass', 'setClassUnion', 'setGeneric', 'setLoadActions', 'setMethod', 'setOldClass', 'makeClassRepresentation', 'show', 'showMethods', 'signature-class', 'slot', 'envRefClass-class', 'testInheritedMethods', 'validObject', '.BasicFunsList'), .Names = c('/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/BasicClasses.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/Classes.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/Documentation.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/EnvironmentClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/GenericFunctions.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/LanguageClasses.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/LinearMethodsList-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/MethodDefinition-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/MethodWithNext-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/Methods.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/MethodsList-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/NextMethod.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/ObjectsWithPackage-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/S3Part.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/S4groupGeneric.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/SClassExtension-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/StructureClasses.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/TraceClasses.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/as.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/callGeneric.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/canCoerce.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/cbind2.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/className.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/classRepresentation-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/classesToAM.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/dotsMethods.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/evalSource.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/findClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/findMethods.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/fixPrevious.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/genericFunction-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/getClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/getMethod.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/getPackageName.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/hasArg.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/implicitGeneric.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/inheritedSlotNames.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/initialize-methods.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/is.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/isSealedMethod.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/localRefClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/method.skeleton.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/new.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/nonStructure-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/promptClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/promptMethods.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/refClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/representation.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/selectSuperClasses.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/setClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/setClassUnion.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/setGeneric.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/setLoadActions.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/setMethod.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/setOldClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/setSClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/show.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/showMethods.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/signature-class.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/slot.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/stdRefClass.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/testInheritedMethods.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/validObject.tex', '/home/lzhao/tmp/RtmpZy1R7l/ltx5573594f0cc9/zBasicFunsList.tex'))); .Internal(toupper(argv[[1]]))"); } @Test @@ -51,6 +50,6 @@ public class TestBuiltin_toupper extends TestBase { assertEval(Ignored.OutputFormatting, "{ toupper(1E100) }"); assertEval("{ m <- matrix(\"hi\") ; toupper(m) }"); - assertEval(Ignored.Unimplemented, "{ toupper(c(a=\"hi\", \"hello\")) }"); + assertEval("{ toupper(c(a=\"hi\", \"hello\")) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unique.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unique.java index ff067fd22894b21b8987226dfe1b0a4c7b7473a5..fb84a6827c203f84b5fa831f81968fb4918e8a20 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unique.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unique.java @@ -189,5 +189,10 @@ public class TestBuiltin_unique extends TestBase { @Test public void testUnique() { assertEval("{x<-factor(c(\"a\", \"b\", \"a\")); unique(x) }"); + + assertEval("{ x<-quote(f(7, 42)); unique(x) }"); + assertEval("{ x<-function() 42; unique(x) }"); + assertEval(Ignored.Unknown, "{ unique(c(1,2,1), incomparables=function() 42) }"); + } } 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 eb8d5dd823630843b0128c10d1b1b529da06f479..fb621527510c5967036e416d241449f044902765 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 @@ -36,6 +36,12 @@ public class TestBuiltin_vapply extends TestBase { assertEval("{ f <- function(a, ...) vapply(a, function(.) identical(a, T, ...), NA); v <- c(1,2,3); f(v) }"); assertEval("{ f<-function(x,y) x-y; w<-c(42, 42); z<-7; vapply(w, f, as.double(NA), x=z) }"); + + assertEval("{ vapply(c(\"foo\", \"bar\"), 42, c(TRUE) }"); + assertEval(Output.IgnoreErrorContext, "{ vapply(c(\"foo\", \"bar\"), function(x) FALSE, function() 42) }"); + 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) }"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vector.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vector.java index 5e7c002f47917a4bb563a2971a52e36a7120e6d1..e218f7e8d356838608ffdff845acebc860915c12 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vector.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vector.java @@ -65,6 +65,11 @@ public class TestBuiltin_vector extends TestBase { assertEval("{ vector(\"numeric\", length=4) }"); assertEval("{ vector(length=3) }"); assertEval("{ x<-as.vector(3); y<-vector(length=x) }"); + + assertEval("{ vector(character()) }"); + assertEval("{ vector(c(\"numeric\", \"numeric\")) }"); + assertEval("{ vector(\"numeric\", integer()) }"); + assertEval("{ vector(\"numeric\", c(7, 42)) }"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmax.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmax.java index 2fe9d80df244312a224515e494fa1fc7ced6783c..ddf4c669f82f8a705cacddb8ba2f8b227097aad2 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmax.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmax.java @@ -24,7 +24,7 @@ public class TestBuiltin_whichmax extends TestBase { @Test public void testwhichmax2() { - assertEval(Ignored.Unknown, "argv <- list(structure(c(TRUE, FALSE), .Names = c('d', 'I(as.numeric(d)^2)'))); .Internal(which.max(argv[[1]]))"); + assertEval("argv <- list(structure(c(TRUE, FALSE), .Names = c('d', 'I(as.numeric(d)^2)'))); .Internal(which.max(argv[[1]]))"); } @Test @@ -34,23 +34,22 @@ public class TestBuiltin_whichmax extends TestBase { @Test public void testwhichmax4() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(NA, 87, 82, 75, 63, 50, 43, 32, 35, 60, 54, 55, 36, 39, NA, NA, 69, 57, 57, 51, 45, 37, 46, 39, 36, 24, 32, 23, 25, 32, NA, 32, 59, 74, 75, 60, 71, 61, 71, 57, 71, 68, 79, 73, 76, 71, 67, 75, 79, 62, 63, 57, 60, 49, 48, 52, 57, 62, 61, 66, 71, 62, 61, 57, 72, 83, 71, 78, 79, 71, 62, 74, 76, 64, 62, 57, 80, 73, 69, 69, 71, 64, 69, 62, 63, 46, 56, 44, 44, 52, 38, 46, 36, 49, 35, 44, 59, 65, 65, 56, 66, 53, 61, 52, 51, 48, 54, 49, 49, 61, NA, NA, 68, 44, 40, 27, 28, 25, 24, 24), .Tsp = c(1945, 1974.75, 4), class = 'ts')); .Internal(which.max(argv[[1]]))"); + assertEval("argv <- list(structure(c(NA, 87, 82, 75, 63, 50, 43, 32, 35, 60, 54, 55, 36, 39, NA, NA, 69, 57, 57, 51, 45, 37, 46, 39, 36, 24, 32, 23, 25, 32, NA, 32, 59, 74, 75, 60, 71, 61, 71, 57, 71, 68, 79, 73, 76, 71, 67, 75, 79, 62, 63, 57, 60, 49, 48, 52, 57, 62, 61, 66, 71, 62, 61, 57, 72, 83, 71, 78, 79, 71, 62, 74, 76, 64, 62, 57, 80, 73, 69, 69, 71, 64, 69, 62, 63, 46, 56, 44, 44, 52, 38, 46, 36, 49, 35, 44, 59, 65, 65, 56, 66, 53, 61, 52, 51, 48, 54, 49, 49, 61, NA, NA, 68, 44, 40, 27, 28, 25, 24, 24), .Tsp = c(1945, 1974.75, 4), class = 'ts')); .Internal(which.max(argv[[1]]))"); } @Test public void testwhichmax5() { - assertEval(Ignored.Unknown, "argv <- list(NULL); .Internal(which.max(argv[[1]]))"); + assertEval("argv <- list(NULL); .Internal(which.max(argv[[1]]))"); } @Test public void testwhichmax6() { - assertEval(Ignored.Unknown, "argv <- list(list()); .Internal(which.max(argv[[1]]))"); + assertEval("argv <- list(list()); .Internal(which.max(argv[[1]]))"); } @Test public void testwhichmax8() { - assertEval(Ignored.Unknown, "argv <- structure(list(x = c(NA, NA)), .Names = 'x');do.call('which.max', argv)"); + assertEval("argv <- structure(list(x = c(NA, NA)), .Names = 'x');do.call('which.max', argv)"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmin.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmin.java index c68a12f92aeb6613580324898e4074e1212331ef..8dbadd6a6face7e01fb9f1830fe277a4b5186edd 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmin.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmin.java @@ -19,41 +19,37 @@ public class TestBuiltin_whichmin extends TestBase { @Test public void testwhichmin1() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(345595, 172795, 69115, 34555, 23035, 11515, 5755, 2875, 1147, 571, 379, 187, 91, 27, 11, 3, 1, 3, 4.42857142857143, 4.73716632443532, 4.86858316221766, 4.95619438740589, 4.97809719370294, 4.98904859685147, 4.99452429842574, 4.99780971937029, 4.99890485968515, 4.99945242984257, 4.99978097193703, 4.99989048596851, 4.99994524298426, 4.9999780971937, 4.99998904859685), .Names = c('1 sec', '2 secs', '5 secs', '10 secs', '15 secs', '30 secs', '1 min', '2 mins', '5 mins', '10 mins', '15 mins', '30 mins', '1 hour', '3 hours', '6 hours', '12 hours', '1 DSTday', '2 DSTdays', '1 week', 'halfmonth', '1 month', '3 months', '6 months', '1 year', '2 years', '5 years', '10 years', '20 years', '50 years', '100 years', '200 years', '500 years', '1000 years'))); .Internal(which.min(argv[[1]]))"); + assertEval("argv <- list(structure(c(345595, 172795, 69115, 34555, 23035, 11515, 5755, 2875, 1147, 571, 379, 187, 91, 27, 11, 3, 1, 3, 4.42857142857143, 4.73716632443532, 4.86858316221766, 4.95619438740589, 4.97809719370294, 4.98904859685147, 4.99452429842574, 4.99780971937029, 4.99890485968515, 4.99945242984257, 4.99978097193703, 4.99989048596851, 4.99994524298426, 4.9999780971937, 4.99998904859685), .Names = c('1 sec', '2 secs', '5 secs', '10 secs', '15 secs', '30 secs', '1 min', '2 mins', '5 mins', '10 mins', '15 mins', '30 mins', '1 hour', '3 hours', '6 hours', '12 hours', '1 DSTday', '2 DSTdays', '1 week', 'halfmonth', '1 month', '3 months', '6 months', '1 year', '2 years', '5 years', '10 years', '20 years', '50 years', '100 years', '200 years', '500 years', '1000 years'))); .Internal(which.min(argv[[1]]))"); } @Test public void testwhichmin2() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(295, 145, 55, 25, 15, 5, 0, 2.5, 4, 4.5, 4.66666666666667, 4.83333333333333, 4.91666666666667, 4.97222222222222, 4.98611111111111, 4.99305555555556, 4.99652777777778, 4.99826388888889, 4.99950396825397, 4.99977184576774, 4.99988592288387, 4.99996197429462, 4.99998098714731, 4.99999049357366, 4.99999524678683, 4.99999809871473, 4.99999904935737, 4.99999952467868, 4.99999980987147, 4.99999990493574, 4.99999995246787, 4.99999998098715, 4.99999999049357), .Names = c('1 sec', '2 secs', '5 secs', '10 secs', '15 secs', '30 secs', '1 min', '2 mins', '5 mins', '10 mins', '15 mins', '30 mins', '1 hour', '3 hours', '6 hours', '12 hours', '1 DSTday', '2 DSTdays', '1 week', 'halfmonth', '1 month', '3 months', '6 months', '1 year', '2 years', '5 years', '10 years', '20 years', '50 years', '100 years', '200 years', '500 years', '1000 years'))); .Internal(which.min(argv[[1]]))"); + assertEval("argv <- list(structure(c(295, 145, 55, 25, 15, 5, 0, 2.5, 4, 4.5, 4.66666666666667, 4.83333333333333, 4.91666666666667, 4.97222222222222, 4.98611111111111, 4.99305555555556, 4.99652777777778, 4.99826388888889, 4.99950396825397, 4.99977184576774, 4.99988592288387, 4.99996197429462, 4.99998098714731, 4.99999049357366, 4.99999524678683, 4.99999809871473, 4.99999904935737, 4.99999952467868, 4.99999980987147, 4.99999990493574, 4.99999995246787, 4.99999998098715, 4.99999999049357), .Names = c('1 sec', '2 secs', '5 secs', '10 secs', '15 secs', '30 secs', '1 min', '2 mins', '5 mins', '10 mins', '15 mins', '30 mins', '1 hour', '3 hours', '6 hours', '12 hours', '1 DSTday', '2 DSTdays', '1 week', 'halfmonth', '1 month', '3 months', '6 months', '1 year', '2 years', '5 years', '10 years', '20 years', '50 years', '100 years', '200 years', '500 years', '1000 years'))); .Internal(which.min(argv[[1]]))"); } @Test public void testwhichmin3() { - assertEval(Ignored.Unknown, "argv <- list(NULL); .Internal(which.min(argv[[1]]))"); + assertEval("argv <- list(NULL); .Internal(which.min(argv[[1]]))"); } @Test public void testwhichmin4() { - assertEval(Ignored.Unknown, "argv <- list(list()); .Internal(which.min(argv[[1]]))"); + assertEval("argv <- list(list()); .Internal(which.min(argv[[1]]))"); } @Test public void testwhichmin5() { - assertEval(Ignored.Unknown, - "argv <- list(c(NA, 0.951840581382975, 0.805577027554469, 0.663985017923499, 0.53717416750558, 0.496765449963868, 0.472038350505409, 0.463306413812878, 0.485896454097402, 0.520777596351646, 0.524391122960607, 0.492063804965834, 0.513821989320989, 0.521702559081969, 0.533525525673351)); .Internal(which.min(argv[[1]]))"); + assertEval("argv <- list(c(NA, 0.951840581382975, 0.805577027554469, 0.663985017923499, 0.53717416750558, 0.496765449963868, 0.472038350505409, 0.463306413812878, 0.485896454097402, 0.520777596351646, 0.524391122960607, 0.492063804965834, 0.513821989320989, 0.521702559081969, 0.533525525673351)); .Internal(which.min(argv[[1]]))"); } @Test public void testwhichmin6() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(NA, 87, 82, 75, 63, 50, 43, 32, 35, 60, 54, 55, 36, 39, NA, NA, 69, 57, 57, 51, 45, 37, 46, 39, 36, 24, 32, 23, 25, 32, NA, 32, 59, 74, 75, 60, 71, 61, 71, 57, 71, 68, 79, 73, 76, 71, 67, 75, 79, 62, 63, 57, 60, 49, 48, 52, 57, 62, 61, 66, 71, 62, 61, 57, 72, 83, 71, 78, 79, 71, 62, 74, 76, 64, 62, 57, 80, 73, 69, 69, 71, 64, 69, 62, 63, 46, 56, 44, 44, 52, 38, 46, 36, 49, 35, 44, 59, 65, 65, 56, 66, 53, 61, 52, 51, 48, 54, 49, 49, 61, NA, NA, 68, 44, 40, 27, 28, 25, 24, 24), .Tsp = c(1945, 1974.75, 4), class = 'ts')); .Internal(which.min(argv[[1]]))"); + assertEval("argv <- list(structure(c(NA, 87, 82, 75, 63, 50, 43, 32, 35, 60, 54, 55, 36, 39, NA, NA, 69, 57, 57, 51, 45, 37, 46, 39, 36, 24, 32, 23, 25, 32, NA, 32, 59, 74, 75, 60, 71, 61, 71, 57, 71, 68, 79, 73, 76, 71, 67, 75, 79, 62, 63, 57, 60, 49, 48, 52, 57, 62, 61, 66, 71, 62, 61, 57, 72, 83, 71, 78, 79, 71, 62, 74, 76, 64, 62, 57, 80, 73, 69, 69, 71, 64, 69, 62, 63, 46, 56, 44, 44, 52, 38, 46, 36, 49, 35, 44, 59, 65, 65, 56, 66, 53, 61, 52, 51, 48, 54, 49, 49, 61, NA, NA, 68, 44, 40, 27, 28, 25, 24, 24), .Tsp = c(1945, 1974.75, 4), class = 'ts')); .Internal(which.min(argv[[1]]))"); } @Test public void testwhichmin8() { - assertEval(Ignored.Unknown, "argv <- structure(list(x = c(NA, NA, Inf)), .Names = 'x');do.call('which.min', argv)"); + assertEval("argv <- structure(list(x = c(NA, NA, Inf)), .Names = 'x');do.call('which.min', argv)"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java index 20a1daf0a17599186f7f7096718a8c55337ebe75..20799e15560ddbacd8e4ba9d6909ade207729891 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java @@ -247,8 +247,8 @@ public class TestMiscBuiltins extends TestBase { @Test public void testWorkingDirectory() { assertEval("{ cur <- getwd(); cur1 <- setwd(getwd()) ; cur2 <- getwd() ; cur == cur1 && cur == cur2 }"); - assertEval(Output.IgnoreErrorContext, "{ setwd(1) }"); - assertEval(Output.IgnoreErrorContext, "{ setwd(character()) }"); + assertEval("{ setwd(1) }"); + assertEval("{ setwd(character()) }"); assertEval("{ cur <- getwd(); cur1 <- setwd(c(cur, \"dummy\")) ; cur2 <- getwd() ; cur == cur1 }"); } @@ -269,7 +269,8 @@ public class TestMiscBuiltins extends TestBase { @Test public void testSimpleRm() { assertEval("{ x <- 200 ; rm(\"x\") ; x }"); - assertEval(Output.IgnoreWarningContext, "{ rm(\"ieps\") }"); + assertEval("{ rm(\"ieps\") }"); + assertEval("{ rm(\"sum\", envir=getNamespace(\"stats\")) }"); assertEval("{ x <- 200 ; rm(\"x\") }"); assertEval("{ x<-200; y<-100; rm(\"x\", \"y\"); x }"); assertEval("{ x<-200; y<-100; rm(\"x\", \"y\"); y }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels10.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels10.R new file mode 100644 index 0000000000000000000000000000000000000000..27a0504a89621d2cbb489e849b0720b8f3e7f263 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels10.R @@ -0,0 +1,16 @@ +# test remote updated of atomic vector with shareable attribute (must stay private) + +if (length(grep("FastR", R.Version()$version.string)) == 1) { + ch <- .fastr.channel.create(1L) + code <- "ch <- .fastr.channel.get(1L); x<-.fastr.channel.receive(ch); x[1]<-7; .fastr.channel.send(ch, x)" + cx <- .fastr.context.spawn(code) + y<-c(42) + attr(y, "foo") <- c("foo", "bar") + .fastr.channel.send(ch, y) + x<-.fastr.channel.receive(ch) + .fastr.context.join(cx) + .fastr.channel.close(ch) + print(c(x,y)) +} else { + print(c(7L, 42L)) +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels11.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels11.R new file mode 100644 index 0000000000000000000000000000000000000000..8a29a1e7f5579e8aa80ff3b55e2cde4377ea2d65 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels11.R @@ -0,0 +1,16 @@ +# test remote updated of atomic vector with serializable attribute (must stay private) + +if (length(grep("FastR", R.Version()$version.string)) == 1) { + ch <- .fastr.channel.create(1L) + code <- "ch <- .fastr.channel.get(1L); x<-.fastr.channel.receive(ch); x[1]<-7; .fastr.channel.send(ch, x)" + cx <- .fastr.context.spawn(code) + y<-c(42) + attr(y, "foo") <- function() 42 + .fastr.channel.send(ch, y) + x<-.fastr.channel.receive(ch) + .fastr.context.join(cx) + .fastr.channel.close(ch) + print(c(x,y)) +} else { + print(c(7L, 42L)) +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels12.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels12.R new file mode 100644 index 0000000000000000000000000000000000000000..ba44457240d723d5a5d6d5f7b2e1a6e124e0dfe1 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels12.R @@ -0,0 +1,16 @@ +# test sending environment with global parent and assigning it remotely (should assign remotely but not locally) + +if (length(grep("FastR", R.Version()$version.string)) == 1) { + ch <- .fastr.channel.create(1L) + code <- "ch <- .fastr.channel.get(1L); env<-.fastr.channel.receive(ch); assign('y', 7, pos=env); .fastr.channel.send(ch, get('x', envir=env))" + cx <- .fastr.context.spawn(code) + env <- new.env(parent = .GlobalEnv) + assign("x", 7, envir=env) + .fastr.channel.send(ch, env) + x<-.fastr.channel.receive(ch) + .fastr.context.join(cx) + .fastr.channel.close(ch) + print(list(x, exists('y', envir=env))) +} else { + print(list(7, FALSE)) +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels13.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels13.R new file mode 100644 index 0000000000000000000000000000000000000000..f9bc278c9bb024c7c3092f18a629552db1cd4393 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels13.R @@ -0,0 +1,18 @@ +# test sending environment with a parent and global grandparent and assigning it remotely (should assign remotely but not locally) + +if (length(grep("FastR", R.Version()$version.string)) == 1) { + ch <- .fastr.channel.create(1L) + code <- "ch <- .fastr.channel.get(1L); env<-.fastr.channel.receive(ch); assign('y', 70, pos=env); assign('z', 420, pos=parent.env(env)); .fastr.channel.send(ch, c(get('w', envir=env), get('x', envir=parent.env(env))))" + cx <- .fastr.context.spawn(code) + parentEnv <- new.env(parent = .GlobalEnv) + env <- new.env(parent = parentEnv) + assign("w", 7, envir=env) + assign("x", 42, envir=parentEnv) + .fastr.channel.send(ch, env) + v<-.fastr.channel.receive(ch) + .fastr.context.join(cx) + .fastr.channel.close(ch) + print(list(v, c(exists('y', envir=env), exists('z', envir=env)))) +} else { + print(list(c(7, 42), c(FALSE, FALSE))) +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels14.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels14.R new file mode 100644 index 0000000000000000000000000000000000000000..4444daa2129b29329ee7f1a8f9e255b43c6f9e17 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels14.R @@ -0,0 +1,18 @@ +# test passing a promise (environment must stay private) + +if (length(grep("FastR", R.Version()$version.string)) == 1) { + ch <- .fastr.channel.create(1L) + code <- "ch <- .fastr.channel.get(1L); x<-.fastr.channel.receive(ch); x[['y']]<-7; .fastr.channel.send(ch, x[['y']])" + cx <- .fastr.context.spawn(code) + y<-c(42) + f <- function(ch, y) { + .fastr.channel.send(ch, environment()) + } + f(ch, y + 1) + x<-.fastr.channel.receive(ch) + .fastr.context.join(cx) + .fastr.channel.close(ch) + print(c(y, x)) +} else { + print(c(42, 7)) +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels15.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels15.R new file mode 100644 index 0000000000000000000000000000000000000000..1f88fd32030ef77602e4ed531a1f25873bc646d3 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels15.R @@ -0,0 +1,16 @@ +# test remote updated of function with shareable attribute (attribute must stay private) + +if (length(grep("FastR", R.Version()$version.string)) == 1) { + ch <- .fastr.channel.create(1L) + code <- "ch <- .fastr.channel.get(1L); f<-.fastr.channel.receive(ch); attr(f, 'foo') <- c('baz', 'bar'); .fastr.channel.send(ch, attr(f, 'foo'))" + cx <- .fastr.context.spawn(code) + f<-function() 42 + attr(f, "foo") <- c("foo", "bar") + .fastr.channel.send(ch, f) + x<-.fastr.channel.receive(ch) + .fastr.context.join(cx) + .fastr.channel.close(ch) + print(list(x, attr(f, "foo"))) +} else { + print(list(c("baz", "bar"), c("foo", "bar"))) +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels16.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels16.R new file mode 100644 index 0000000000000000000000000000000000000000..9c1470b87072bafaae37c77086b404a807d931f7 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels16.R @@ -0,0 +1,18 @@ +# test recursion - sending environment containing vector with same environment attribute + +if (length(grep("FastR", R.Version()$version.string)) == 1) { + ch <- .fastr.channel.create(1L) + code <- "ch <- .fastr.channel.get(1L); env<-.fastr.channel.receive(ch); .fastr.channel.send(ch, get('v', envir=env))" + cx <- .fastr.context.spawn(code) + env <- new.env(parent = .GlobalEnv) + v <- c(7) + attr(v, "env") <- env + assign("v", v, envir=env) + .fastr.channel.send(ch, env) + x<-.fastr.channel.receive(ch) + .fastr.context.join(cx) + .fastr.channel.close(ch) + print(c(v, x)) +} else { + print(c(7, 7)) +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels17.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels17.R new file mode 100644 index 0000000000000000000000000000000000000000..68cc2c1f8467af241a592f689a0420c43fe56fc8 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels17.R @@ -0,0 +1,18 @@ +# test passing a function (environment must stay private) + +if (length(grep("FastR", R.Version()$version.string)) == 1) { + ch <- .fastr.channel.create(1L) + code <- "ch <- .fastr.channel.get(1L); f<-.fastr.channel.receive(ch); env <- environment(f); env[['x']] <- 7; .fastr.channel.send(ch, env[['x']])" + cx <- .fastr.context.spawn(code) + env <- new.env() + env[["x"]] <- 42 + f <- function() 42 + environment(f) <- env + .fastr.channel.send(ch, f) + y <- .fastr.channel.receive(ch) + .fastr.context.join(cx) + .fastr.channel.close(ch) + print(c(env[["x"]], y)) +} else { + print(c(42, 7)) +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels2.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels2.R index 1879ea428d7f3aa5464ba037403ac00025d1a2ce..3e4b27396ea2c358d0354d85dba0e9b678ac93fe 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels2.R +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels2.R @@ -6,7 +6,7 @@ if (length(grep("FastR", R.Version()$version.string)) == 1) { cx <- .fastr.context.spawn(code) y<-list(c(42)) .fastr.channel.send(ch, y) - x<-fastr.channel.receive(ch) + x<-.fastr.channel.receive(ch) .fastr.context.join(cx) .fastr.channel.close(ch) print(c(x,y)) 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 202529dcc7d37f277fdc08f97888b135a6926ad3..bce570f903c34c7adf70c8a76b6332518dddbad4 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 @@ -148,7 +148,7 @@ public class TestFunctions extends TestBase { assertEval("{ f <- function(a,b,c,d) { a + b } ; f(1,x=1,2,3,4) }"); assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ x<-function(y, b){1} ; x(y=1, 2, 3, z = 5) }"); - assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ x<-function(a){1} ; x(1,) }"); + assertEval("{ x<-function(a){1} ; x(1,) }"); // note exactly GNU-R message assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ f <- function(a,a) {1} }"); @@ -263,7 +263,7 @@ public class TestFunctions extends TestBase { assertEval("{ f <- function(...) { g <- function() { ..1 } ; g() } ; f(a=2) }"); assertEval("{ f <- function(...) { ..1 <- 2 ; ..1 } ; f(z = 1) }"); assertEval("{ f <- function(...) { ..1 <- 2 ; get(\"..1\") } ; f(1,2,3,4) }"); - assertEval(Output.IgnoreErrorContext, "{ f <- function(...) { get(\"..1\") } ; f(1,2,3,4) }"); + assertEval("{ f <- function(...) { get(\"..1\") } ; f(1,2,3,4) }"); assertEval("{ g <- function(a,b) { a + b } ; f <- function(...) { g(...) } ; f(1,2) }"); assertEval("{ g <- function(a,b,x) { a + b * x } ; f <- function(...) { g(...,x=4) } ; f(b=1,a=2) }"); @@ -331,7 +331,7 @@ public class TestFunctions extends TestBase { assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ lapply(1:3, \"dummy\") }"); assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ f <- function(a, barg, bextra, dummy) { a + barg } ; g <- function(...) { f(a=1, ..., x=2,z=3) } ; g(1) }"); - assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ f <- function(a, barg, bextra, dummy) { a + barg } ; g <- function(...) { f(a=1, ...,,,) } ; g(1) }"); + 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) }"); } 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 7a2e66057d0a81aba32d486120cc75937c8537f1..7a96e9c53f02026819202b99c8a88fee03933ca8 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 @@ -22,7 +22,6 @@ */ package com.oracle.truffle.r.test.generate; -import java.io.IOException; import java.util.ArrayDeque; import java.util.Arrays; import java.util.Deque; @@ -38,8 +37,8 @@ import com.oracle.truffle.r.runtime.RCmdOptions; import com.oracle.truffle.r.runtime.RCmdOptions.Client; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RStartParams; import com.oracle.truffle.r.runtime.RSource; +import com.oracle.truffle.r.runtime.RStartParams; import com.oracle.truffle.r.runtime.context.ConsoleHandler; import com.oracle.truffle.r.runtime.context.ContextInfo; import com.oracle.truffle.r.runtime.context.Engine.IncompleteSourceException; @@ -50,8 +49,14 @@ import com.oracle.truffle.r.test.TestBase; public final class FastRSession implements RSession { - private static final int DEFAULT_TIMEOUT = System.getProperty("DisableTestTimeout") != null ? Integer.MAX_VALUE : 10000; - private static final int LONG_TIMEOUT = System.getProperty("DisableTestTimeout") != null ? Integer.MAX_VALUE : 60000; + private static final String TEST_TIMEOUT_PROPERTY = "FastRTestTimeout"; + private static final String DISABLE_TIMEOUT_PROPERTY = "DisableTestTimeout"; // legacy + private static int timeoutValue = 10000; + /** + * The long timeout is used for package installation and currently needs to be 5 mins for the + * {@code Matrix} package. + */ + private static int longTimeoutValue = 300000; /** * A (virtual) console handler that collects the output in a {@link StringBuilder} for @@ -139,7 +144,7 @@ public final class FastRSession implements RSession { public static final Source GET_CONTEXT = RSource.fromTextInternal("invisible(.fastr.context.get())", RSource.Internal.GET_CONTEXT); - public PolyglotEngine createTestContext(ContextInfo contextInfoArg) { + public ContextInfo checkContext(ContextInfo contextInfoArg) { create(); ContextInfo contextInfo; if (contextInfoArg == null) { @@ -147,36 +152,48 @@ public final class FastRSession implements RSession { } else { contextInfo = contextInfoArg; } - return contextInfo.createVM(); + return contextInfo; } public ContextInfo createContextInfo(ContextKind contextKind) { RStartParams params = new RStartParams(RCmdOptions.parseArguments(Client.RSCRIPT, new String[0], false), false); - return ContextInfo.create(params, contextKind, mainContext, consoleHandler, TimeZone.getTimeZone("CET")); + return ContextInfo.create(params, null, contextKind, mainContext, consoleHandler, TimeZone.getTimeZone("GMT")); } private FastRSession() { + if (System.getProperty(DISABLE_TIMEOUT_PROPERTY) != null) { + timeoutValue = Integer.MAX_VALUE; + longTimeoutValue = Integer.MAX_VALUE; + } else if (System.getProperty(TEST_TIMEOUT_PROPERTY) != null) { + int timeoutGiven = Integer.parseInt(System.getProperty(TEST_TIMEOUT_PROPERTY)); + timeoutValue = timeoutGiven * 1000; + // no need to scale longTimeoutValue + } consoleHandler = new TestConsoleHandler(); try { RStartParams params = new RStartParams(RCmdOptions.parseArguments(Client.RSCRIPT, new String[]{"--no-restore"}, false), false); - ContextInfo info = ContextInfo.create(params, ContextKind.SHARE_NOTHING, null, consoleHandler); + ContextInfo info = ContextInfo.create(params, null, ContextKind.SHARE_NOTHING, null, consoleHandler); main = info.createVM(); - try { - mainContext = main.eval(GET_CONTEXT).as(RContext.class); - emitIO(); - } catch (IOException e) { - throw new RuntimeException("error while retrieving test context", e); - } + mainContext = main.eval(GET_CONTEXT).as(RContext.class); } finally { System.out.print(consoleHandler.buffer.toString()); } } @Override + public String eval(TestBase testClass, String expression, ContextInfo contextInfo, boolean longTimeout) throws Throwable { + evalAsObject(testClass, expression, contextInfo, longTimeout); + return consoleHandler.buffer.toString(); + } + + /** + * Returns the actual object from evaluating expression. Used (and result ignored) by + * {@link #eval} but also used for package installation via the {@code system2} command, where + * the result is used to check whether the installation succeeded. + */ @SuppressWarnings("deprecation") - public String eval(String expression, ContextInfo contextInfo, boolean longTimeout) throws Throwable { + public Object evalAsObject(TestBase testClass, String expression, ContextInfo contextInfo, boolean longTimeout) throws Throwable { consoleHandler.reset(); - EvalThread thread = evalThread; if (thread == null || !thread.isAlive() || contextInfo != thread.contextInfo) { thread = new EvalThread(contextInfo); @@ -185,12 +202,13 @@ public final class FastRSession implements RSession { evalThread = thread; } - thread.push(expression); + thread.push(testClass, expression); try { - if (!thread.await(longTimeout ? LONG_TIMEOUT : DEFAULT_TIMEOUT)) { + if (!thread.await(longTimeout ? longTimeoutValue : timeoutValue)) { consoleHandler.println("<timeout>"); thread.stop(); + evalThread.ensureContextDestroyed(); evalThread = null; throw new TimeoutException(); } @@ -201,7 +219,7 @@ public final class FastRSession implements RSession { evalThread = null; throw thread.killedByException; } - return consoleHandler.buffer.toString(); + return evalThread.result; } private final class EvalThread extends RContext.ContextThread { @@ -211,14 +229,24 @@ public final class FastRSession implements RSession { private final Semaphore entry = new Semaphore(0); private final Semaphore exit = new Semaphore(0); private final ContextInfo contextInfo; - + private TestBase testClass; + private Object result; + + /** + * Create an evaluation thread (to handle timeouts). + * + * @param contextInfo {@code null} for a lightweight test context, else an existing one to + * use. + */ EvalThread(ContextInfo contextInfo) { super(null); this.contextInfo = contextInfo; + setDaemon(true); } - public void push(String exp) { + public void push(TestBase testClassArg, String exp) { this.expression = exp; + this.testClass = testClassArg; this.entry.release(); } @@ -226,6 +254,15 @@ public final class FastRSession implements RSession { return exit.tryAcquire(millisTimeout, TimeUnit.MILLISECONDS); } + /** + * In case the vm is not disposed by the {@code finally} clause in run after a timeout, + * (which should not happen), we explicitly destroy the context, to avoid subsequent errors + * relating to multiple children of a single SHARED_RW context. + */ + public void ensureContextDestroyed() { + context.destroy(); + } + @Override public void run() { while (killedByException == null) { @@ -235,17 +272,31 @@ public final class FastRSession implements RSession { break; } try { - PolyglotEngine vm = createTestContext(contextInfo); + ContextInfo actualContextInfo = checkContext(contextInfo); + // set up some interop objects used by fastr-specific tests: + PolyglotEngine.Builder builder = PolyglotEngine.newBuilder(); + if (testClass != null) { + testClass.addPolyglotSymbols(builder); + } + PolyglotEngine vm = actualContextInfo.createVM(builder); consoleHandler.setInput(expression.split("\n")); try { String input = consoleHandler.readLine(); while (input != null) { Source source = RSource.fromTextInternal(input, RSource.Internal.UNIT_TEST); try { - vm.eval(source); + try { + result = vm.eval(source).get(); + // checked exceptions are wrapped in RuntimeExceptions + } catch (RuntimeException e) { + if (e.getCause() instanceof com.oracle.truffle.api.vm.IncompleteSourceException) { + throw e.getCause().getCause(); + } else { + throw e; + } + } input = consoleHandler.readLine(); - emitIO(); - } catch (IncompleteSourceException | com.oracle.truffle.api.vm.IncompleteSourceException e) { + } catch (IncompleteSourceException e) { String additionalInput = consoleHandler.readLine(); if (additionalInput == null) { throw e; @@ -258,23 +309,16 @@ public final class FastRSession implements RSession { } } catch (ParseException e) { e.report(consoleHandler); + } catch (RError e) { + // nothing to do } catch (Throwable t) { - if (t instanceof IOException) { - if (t.getCause() instanceof RError || t.getCause() instanceof RInternalError) { - t = t.getCause(); + if (!TestBase.ProcessFailedTests) { + if (t instanceof RInternalError) { + RInternalError.reportError(t); } + t.printStackTrace(); } - if (t instanceof RError) { - // nothing to do - } else { - if (!TestBase.ProcessFailedTests) { - if (t instanceof RInternalError) { - RInternalError.reportError(t); - } - t.printStackTrace(); - } - killedByException = t; - } + killedByException = t; } finally { exit.release(); } @@ -286,8 +330,4 @@ public final class FastRSession implements RSession { public String name() { return "FastR"; } - - @SuppressWarnings("unused") - static void emitIO() throws IOException { - } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java index 793c65dbafdf21ccbce6b88a4fc868c5d56baa8e..7b8486ff98a134cc48165ccd7545f8a6f14b8da2 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java @@ -27,7 +27,9 @@ import java.io.InputStream; import java.io.OutputStream; import java.nio.file.FileSystems; import java.nio.file.Path; +import java.util.concurrent.TimeUnit; +import com.oracle.truffle.r.runtime.ProcessOutputManager; import com.oracle.truffle.r.runtime.REnvVars; import com.oracle.truffle.r.runtime.RVersionNumber; import com.oracle.truffle.r.runtime.context.ContextInfo; @@ -50,6 +52,8 @@ public class GnuROneShotRSession implements RSession { private static final String[] GNUR_COMMANDLINE = new String[]{"R", "--vanilla", "--slave", "--silent"}; private static final String FASTR_TESTGEN_GNUR = "FASTR_TESTGEN_GNUR"; private static final String NATIVE_PROJECT = "com.oracle.truffle.r.native"; + private static final int DEFAULT_TIMEOUT_MINS = 5; + private static int timeoutMins = DEFAULT_TIMEOUT_MINS; //@formatter:off protected static final String GNUR_OPTIONS = @@ -65,6 +69,14 @@ public class GnuROneShotRSession implements RSession { protected static byte[] QUIT = "q()\n".getBytes(); protected Process createGnuR() throws IOException { + String timeout = System.getenv("FASTR_TESTGEN_TIMEOUT"); + if (timeout != null) { + try { + timeoutMins = Integer.parseInt(timeout); + } catch (NumberFormatException ex) { + System.err.println("ignoring invalid value for FASTR_TESTGEN_TIMEOUT"); + } + } String testGenGnuR = System.getenv(FASTR_TESTGEN_GNUR); if (testGenGnuR != null) { if (testGenGnuR.length() == 0 || testGenGnuR.equals("internal")) { @@ -76,8 +88,8 @@ public class GnuROneShotRSession implements RSession { } ProcessBuilder pb = new ProcessBuilder(GNUR_COMMANDLINE); - // fix time zone to "CET" (to create consistent expected output) - pb.environment().put("TZ", "CET"); + // fix time zone to "GMT" (to create consistent expected output) + pb.environment().put("TZ", "GMT"); pb.environment().remove("R_HOME"); // don't confuse GnuR with FastR! pb.redirectErrorStream(true); Process p = pb.start(); @@ -85,32 +97,27 @@ public class GnuROneShotRSession implements RSession { return p; } - protected String readAvailable(InputStream gnuRoutput) throws IOException { - int n = gnuRoutput.available(); - byte[] data = new byte[n]; - gnuRoutput.read(data); - return new String(data); - } - @Override - public String eval(String expression, ContextInfo contextInfo, boolean longTimeout) { + public String eval(TestBase testBase, String expression, ContextInfo contextInfo, boolean longTimeout) throws Throwable { if (expression.contains("library(") && !TestBase.generatingExpected()) { System.out.println("=============================================="); - System.out.println("LIBRARY LOADING WHILE CREATING EXPECTED OUTPUT"); + System.out.println("LIBRARY LOADING WHEN NOT GENERATING EXPECTED OUTPUT"); System.out.println("creating expected output for these tests only works during test output"); System.out.println("generation (mx rtestgen), and will otherwise create corrupted output."); } - try { - Process p = createGnuR(); - InputStream gnuRoutput = p.getInputStream(); - OutputStream gnuRinput = p.getOutputStream(); - send(gnuRinput, expression.getBytes(), NL, QUIT); - p.waitFor(); - return readAvailable(gnuRoutput); - } catch (IOException | InterruptedException ex) { - System.err.print("exception: " + ex); - return null; + Process p = createGnuR(); + InputStream gnuRoutput = p.getInputStream(); + OutputStream gnuRinput = p.getOutputStream(); + ProcessOutputManager.OutputThreadVariable readThread = new ProcessOutputManager.OutputThreadVariable("gnur eval", gnuRoutput); + readThread.start(); + send(gnuRinput, expression.getBytes(), NL, QUIT); + int thisTimeout = longTimeout ? timeoutMins * 2 : timeoutMins; + if (!p.waitFor(thisTimeout, TimeUnit.MINUTES)) { + throw new RuntimeException(String.format("GNU R process timed out on: '%s'\n", expression)); } + readThread.join(); + return new String(readThread.getData(), 0, readThread.getTotalRead()); + } protected void send(OutputStream gnuRinput, byte[]... data) throws IOException { @@ -125,8 +132,4 @@ public class GnuROneShotRSession implements RSession { return "GnuR one-shot"; } - public static void main(String[] args) { - String testGenGnuR = System.getenv(FASTR_TESTGEN_GNUR); - System.out.printf("%s='%s'%n", FASTR_TESTGEN_GNUR, testGenGnuR); - } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.java index e42c022411ae2fccc7273fc42ac9d5be625249ff..a1596b25bb0679a326947af47f88b037b0c0e501 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.test.generate; import com.oracle.truffle.r.runtime.context.ContextInfo; +import com.oracle.truffle.r.test.TestBase; /** * Represents an R session that may be interactive or non-interactive. @@ -34,8 +35,15 @@ public interface RSession { * If {@code contextInfo is non-null} it is used for the evaluation, else the choice is left to * the implementation. If the implementation uses timeouts, {@code longTimeout} indicates that * this evaluation is expected to take (much) longer than normal. + * + * If {@code testClass} is not null, then it represents the subclass of {@link TestBase} that + * caused the evaluation. + * + * This result will always be non-null or an exception will be thrown in, say, a timeout + * occurring. + * */ - String eval(String expression, ContextInfo contextInfo, boolean longTimeout) throws Throwable; + String eval(TestBase testClass, String expression, ContextInfo contextInfo, boolean longTimeout) throws Throwable; /** * A name to identify the session. diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/TestOutputManager.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/TestOutputManager.java index 02d8aff7a4e39c28e9cabc3bfd8fb3333512dfa6..8924cf1f79706c76824bfaf45439036173938e27 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/TestOutputManager.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/TestOutputManager.java @@ -130,6 +130,10 @@ public class TestOutputManager { this.rSessionName = session.name(); } + public RSession getRSession() { + return rSession; + } + /** * Associates a name with the manager, for the case where {@link #rSession} is unset. */ @@ -360,7 +364,7 @@ public class TestOutputManager { String expected = null; if (!checkOnly) { try { - expected = rSession.eval(test, null, false); + expected = rSession.eval(null, test, null, false); } catch (Throwable e) { throw RInternalError.shouldNotReachHere("unexpected exception thrown by GNUR session: " + 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 6a7c81b9e40036a03dbe67653413d32b6151409a..6ef52e9c768594efaf0c4ffe72cc42efc88ccc7d 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 @@ -23,13 +23,10 @@ package com.oracle.truffle.r.test.library.base; 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.runtime.REnvVars; import com.oracle.truffle.r.test.TestBase; public class TestConnections extends TestBase { @@ -37,11 +34,7 @@ public class TestConnections extends TestBase { private final Path testDirPath; TestDir() { - Path rpackages = Paths.get(REnvVars.rHome(), "com.oracle.truffle.r.test"); - testDirPath = TestBase.relativize(rpackages.resolve("library.base.conn")); - if (!testDirPath.toFile().exists()) { - testDirPath.toFile().mkdir(); - } + testDirPath = TestBase.createTestDir("com.oracle.truffle.r.test.library.base.conn"); } String[] subDir(String p) { @@ -59,7 +52,7 @@ public class TestConnections extends TestBase { @AfterClass public static void teardownTestDir() { if (!deleteDir(testDir.testDirPath)) { - throw new AssertionError(); + System.err.println("WARNING: error deleting : " + testDir.testDirPath); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestEnvironments.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestEnvironments.java index 31066d5f1b6466d551d573862b659c17ca64f7a4..44ac9c7cfa00022ca8a01c1cd5293600ad42b13c 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestEnvironments.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestEnvironments.java @@ -56,8 +56,8 @@ public class TestEnvironments extends TestBase { assertEval("{ x <- 3 ; f <- function() { exists(\"x\", inherits=FALSE) } ; f() }"); assertEval("{ x <- 2 ; y <- 3 ; rm(\"y\") ; ls() }"); - assertEval(Output.IgnoreErrorContext, "{ x <- 2 ; rm(\"x\") ; get(\"x\") }"); - assertEval(Output.IgnoreErrorContext, "{ get(\"x\") }"); + assertEval("{ x <- 2 ; rm(\"x\") ; get(\"x\") }"); + assertEval("{ get(\"x\") }"); assertEval("{ f <- function() { assign(\"x\", 1) ; y <- 2 ; ls() } ; sort(f()) }"); assertEval("{ f <- function() { x <- 1 ; y <- 2 ; ls() } ; sort(f()) }"); @@ -238,26 +238,26 @@ public class TestEnvironments extends TestBase { assertEval("{ e<-new.env(); assign(\"a\", 1, e); lockBinding(\"a\", e); bindingIsLocked(\"a\", e) }"); // rm - assertEval(Output.IgnoreErrorContext, "{ rm(\"foo\", envir = baseenv()) }"); - assertEval(Output.IgnoreErrorContext, "{ e<-new.env(); assign(\"a\", 1, e) ; lockEnvironment(e); rm(\"a\",envir = e); }"); + assertEval("{ rm(\"foo\", envir = baseenv()) }"); + assertEval("{ e<-new.env(); assign(\"a\", 1, e) ; lockEnvironment(e); rm(\"a\",envir = e); }"); // ok to removed a locked binding assertEval("{ e<-new.env(); assign(\"a\", 1, e) ; lockBinding(\"a\", e); rm(\"a\",envir = e); ls() }"); assertEval("{ e<-new.env(); assign(\"a\", 1, e) ; rm(\"a\",envir = e); ls() }"); // get - assertEval(Output.IgnoreErrorContext, "{ e<-new.env(); get(\"x\", e) }"); + assertEval("{ e<-new.env(); get(\"x\", e) }"); assertEval("{ e<-new.env(); x<-1; get(\"x\", e) }"); assertEval("{ e<-new.env(); assign(\"x\", 1, e); get(\"x\", e) }"); - assertEval(Output.IgnoreErrorContext, "{ e<-new.env(); x<-1; get(\"x\", e, inherits=FALSE) }"); - assertEval(Output.IgnoreErrorContext, "{ e<-new.env(parent=emptyenv()); x<-1; get(\"x\", e) }"); + assertEval("{ e<-new.env(); x<-1; get(\"x\", e, inherits=FALSE) }"); + assertEval("{ e<-new.env(parent=emptyenv()); x<-1; get(\"x\", e) }"); // misc - assertEval(Output.IgnoreErrorContext, "{ h <- new.env(parent=emptyenv()) ; assign(\"y\", 2, h) ; get(\"z\", h) }"); + assertEval("{ h <- new.env(parent=emptyenv()) ; assign(\"y\", 2, h) ; get(\"z\", h) }"); assertEval("{ plus <- function(x) { function(y) x + y } ; plus_one <- plus(1) ; ls(environment(plus_one)) }"); assertEval("{ ls(.GlobalEnv) }"); assertEval("{ x <- 1 ; ls(.GlobalEnv) }"); - assertEval(Output.IgnoreErrorContext, "{ ph <- new.env(parent=emptyenv()) ; h <- new.env(parent=ph) ; assign(\"x\", 10, h, inherits=TRUE) ; get(\"x\", ph)}"); - assertEval(Output.IgnoreErrorContext, "{ ph <- new.env() ; h <- new.env(parent=ph) ; assign(\"x\", 2, h) ; assign(\"x\", 10, h, inherits=TRUE) ; get(\"x\", ph)}"); + assertEval("{ ph <- new.env(parent=emptyenv()) ; h <- new.env(parent=ph) ; assign(\"x\", 10, h, inherits=TRUE) ; get(\"x\", ph)}"); + assertEval("{ ph <- new.env() ; h <- new.env(parent=ph) ; assign(\"x\", 2, h) ; assign(\"x\", 10, h, inherits=TRUE) ; get(\"x\", ph)}"); assertEval("{ h <- new.env(parent=globalenv()) ; assign(\"x\", 10, h, inherits=TRUE) ; x }"); assertEval("{ ph <- new.env() ; h <- new.env(parent=ph) ; assign(\"x\", 10, h, inherits=TRUE) ; 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 4dc124ca5c8513ffd5589e4a61be7be0b720ccfb..9aa145f1373cbadd6a7c110df8f1a2364744b525 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 @@ -307,6 +307,7 @@ public class TestSimpleArithmetic extends TestBase { public void testVectorsComplex() { assertEval("{ 1:4+c(1,2+2i) }"); assertEval("{ c(1,2+2i)+1:4 }"); + assertEval("x <- c(NaN, 3+2i); xre <- Re(x); xim <- (0+1i) * Im(x); xre + xim"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleAttributes.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleAttributes.java index 09cb88455c95219ff80bf75fea4d811711ee9b07..7ba01a8b568ef3c5d1bbf2f98d26cc9f704347cb 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleAttributes.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleAttributes.java @@ -48,6 +48,17 @@ public class TestSimpleAttributes extends TestBase { assertEval("{ f<-function(y) attr(y, \"foo\")<-NULL; x<-function() 42; attr(x, \"foo\")<-\"foo\"; s<-\"bar\"; switch(s, f(x)); x }"); assertEval("{ setClass(\"foo\", representation(j=\"numeric\")); x<-new(\"foo\", j=42); attr(x, \"foo\")<-\"foo\"; y<-x; attributes(y)<-NULL; x }"); + + assertEval("{ x<-42; attributes(x)<-list(.Environment=globalenv()); environment(x) }"); + assertEval("{ x<-42; attributes(x)<-list(.Environment=globalenv()); attributes(x) }"); + assertEval("{ x<-42; attributes(x)<-list(.Environment=globalenv()); attributes(x)<-NULL; environment(x) }"); + assertEval("{ x<-42; attr(x, '.Environment')<-globalenv(); environment(x) }"); + assertEval("{ x<-42; attr(x, '.Environment')<-globalenv(); attr(x, '.Environment') }"); + assertEval("{ x<-42; attr(x, '.Environment')<-globalenv(); attr(x, '.Environment')<-NULL; environment(x) }"); + assertEval("{ f<-function() 42; attributes(f)<-list(.Environment=baseenv()); environment(f) }"); + assertEval("{ f<-function() 42; attributes(f)<-list(.Environment=baseenv()); attributes(f) }"); + assertEval("{ f<-function() 42; attr(f, '.Environment')<-baseenv(); environment(f) }"); + assertEval("{ f<-function() 42; attr(f, '.Environment')<-baseenv(); attr(f, '.Environment') }"); } @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 8cd12813e576c9f26f540e7f06f9de7634bcb11f..dcd71d109a2ead6c90897cc30e196f7870a365cf 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 @@ -92,4 +92,58 @@ public class TestSimpleLists extends TestBase { public void testListArgumentEvaluation() { assertEval("{ a <- c(0,0,0) ; f <- function() { g <- function() { a[2] <<- 9 } ; g() } ; u <- function() { a <- c(1,1,1) ; f() ; a } ; list(a,u()) }"); } + + @Test + public void testListRefcounting() { + // (LS) more tests like this are needed... + assertEval("a <- list(x=c(1,2,3)); b <- a; a$x[[1]] <- 4; b"); + assertEval("a <- list(); a$x <- c(1,2,3); b <- a; a$x[[1]] <- 4; b"); + assertEval("a <- list(); a$y <- 'dummy'; a$x <- c(1,2,3); b <- a; a$x[[1]] <- 4; b"); + assertEval("a <- list(); a$y <- 'dummy'; b <- a; a$x <- c(1,2,3); a$x[[1]] <- 4; b"); + assertEval("a <- list(x=c(1,2,10)); b <- list(); b$x <- c(1,42); swap <- a; a <- b; b <- swap; a$x[[2]] <- 3; list(a=a, b=b)"); + assertEval("z <- c(1,4,8); a<-list(); a$x <- z; a$x[[1]] <- 42; list(a=a, z=z)"); + + // with a scalar + assertEval("a <- list(x=1); b <- a; a$x[[1]] <- 42; list(a=a,b=b)"); + + // recursive + assertEval("a <- list(x=list(y=c(1,2,4))); b <- a; b$x$y[[1]] <- 42; list(a=a,b=b)"); + assertEval("a <- list(x=list(y=c(1,2,4))); b <- a$x; b$y[[1]] <- 42; list(a=a,b=b)"); + assertEval("a <- list(x=list(y=c(1,2,4))); b <- a$x; c <- b; c$y[[1]] <- 42; list(a=a,b=b,c=c)"); + assertEval("l <- list(k=list()); k <- list(x=c(1,10)); l$k <- k; l$k$x[1] <- 42; list(l_k=l$k$x, k=k$x);"); + + // parameters + assertEval("f <- function(l) l$x[[1]]<-42; a <- list(x=c(1,2,4)); b <- a; f(b); list(a=a, b=b)"); + assertEval("f <- function(l) l$x[[1]]<-42; a <- list(x=c(1,2,4)); f(a); a"); + assertEval("f <- function(l) l; a <- list(x=c(1,2,4)); b <- f(a); b$x[[1]] <- 42; list(a=a, b=b)"); + + // lists returned from built-ins + assertEval("r <- split(1,1); r[[1]] / 2; r;"); + assertEval("r <- split(1,1); x <- r; r[[1]] <- 42; x;"); + assertEval("x <- c(1,2,3); l <- list(x); x[[1]] <- 42; l;"); + + // (potential) cycles + assertEval(Ignored.Unimplemented, "l <- list(list(list())); l[[1]][[1]] <- l; l"); + assertEval("l <- list(k=list()); k <- list(l=list()); l$k <- k; k$l <- l; k$l$x <- 42; list(k=k, l=l)"); + assertEval("l <- list(x=list()); v <- list(y=42,x=list()); v$x <- l; l$x <- v; l$y <- 44; k <- v; k$y <- 45; list(l=l,v=v,k=k);"); + } + + @Test + public void testListDuplication() { + assertEvalFastR("l <- list(x=c(3,4,5)); id <- .fastr.identity(l); l$x[2] <- 10; id == .fastr.identity(l)", "TRUE"); + assertEvalFastR("l <- list(x=c(3,4,5)); id <- .fastr.identity(l$x); l$x[2] <- 10; id == .fastr.identity(l$x)", "TRUE"); + assertEvalFastR("l <- list(x=c(3,4,5)); id <- .fastr.identity(l$x); l$x <- 1:10; id == .fastr.identity(l$x)", "FALSE"); + } + + @Test + public void testAvoidingCopying() { + // these tests should not print copying related output + assertEval("a<-list(); a$x <- c(1,2,3); invisible(tracemem(a$x)); a$x[[1]] <- a$x[[2]] * 3; a$x"); + assertEval("a<-list(); a$x <- c(1,2,3); invisible(tracemem(a$x)); a$y <- 'dummy'; a$x[[1]] <- a$x[[2]] * 3; a$x"); + assertEval("a<-list(); a$x <- c(1,2,3); ident <- function(q)q; invisible(tracemem(a$x)); a$x[[1]] <- ident(a$x[[2]]); a$x"); + assertEval("z <- c(1,4,8); invisible(tracemem(z)); a<-list(); a$x <- z;"); + assertEval("l <- list(x=c(NA,NA)); l$x[1] <- 42; invisible(tracemem(l$x)); l$x[2] <- 42;"); + assertEval("l <- list(); l$x <- c(NA); length(l$x) <- 10; l$x[1] <- 42; invisible(tracemem(l$x)); l$x[2:9] <- 42;"); + assertEval("x <- list(c(1,2,3)); invisible(tracemem(x)); x[[1]] <- 42;"); + } } 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 d7e37be0a2c980b86971810039f3e780ac60043b..f9aa5be4f97b1109f7b2e7357579484bc6fb63eb 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 @@ -1503,7 +1503,7 @@ public class TestSimpleVectors extends TestBase { assertEval("{ b <- list(1+2i,3+4i) ; dim(b) <- c(2,1) ; b[3] <- NULL ; b }"); // weird problems with fluctuating error messages in GNU R - assertEval("{ f <- function(b,v) { b[[2]] <- v ; b } ; f(c(\"a\",\"b\"),\"d\") ; f(c(\"a\",\"b\"),NULL) }"); + assertEval(Ignored.Unstable, "{ f <- function(b,v) { b[[2]] <- v ; b } ; f(c(\"a\",\"b\"),\"d\") ; f(c(\"a\",\"b\"),NULL) }"); assertEval(Ignored.Unstable, Output.IgnoreErrorContext, "{ x <- 4:10 ; x[[\"z\"]] <- NULL ; x }"); } @@ -2066,7 +2066,7 @@ public class TestSimpleVectors extends TestBase { assertEval("{ f <- function(b,i,v) { b[[i]] <- v ; b } ; f(list(1,2,b=list(a=1)),c(\"b\",\"a\"),10) ; f(list(a=1,b=c(a=2)),1+2i,1:3) }"); assertEval(" { f <- function(b,i,v) { b[[i]] <- v ; b } ; f(list(1,2,b=list(a=1)),c(\"b\",\"a\"),10) ; f(list(a=1,b=c(a=2)),c(TRUE,TRUE),3) }"); assertEval("{ f <- function(b,i,v) { b[[i]] <- v ; b } ; f(list(1,2,b=list(a=1)),c(\"b\",\"a\"),10) ; f(f,TRUE,3) }"); - assertEval("{ f <- function(b,i,v) { b[[i]] <- v ; b } ; f(list(1,2,b=list(a=1)),c(\"b\",\"a\"),10) ; f(c(a=1,b=2),\"b\",NULL) }"); + assertEval(Ignored.Unstable, "{ f <- function(b,i,v) { b[[i]] <- v ; b } ; f(list(1,2,b=list(a=1)),c(\"b\",\"a\"),10) ; f(c(a=1,b=2),\"b\",NULL) }"); assertEval("{ f <- function(b,i,v) { b[[i]] <- v ; b } ; f(list(1,2,b=list(a=1)),c(\"b\",\"a\"),10) ; f(c(a=1,b=2),\"b\",as.raw(12)) }"); assertEval(Output.IgnoreErrorMessage, "{ f <- function(b,i,v) { b[[i]] <- v ; b } ; f(list(1,2,b=list(a=1)),c(\"b\",\"a\"),10) ; f(c(a=1,b=2),c(1+2i,3+4i),as.raw(12)) }"); assertEval("{ l <- list(a=1,b=2,cd=list(c=3,d=4)) ; x <- list(l,xy=list(x=l,y=l)) ; x[[c(2,2,3,2)]] <- 10 ; l }"); @@ -2075,7 +2075,7 @@ public class TestSimpleVectors extends TestBase { assertEval("{ l <- matrix(list(1,2)) ; l[[3]] <- NULL ; l }"); assertEval("{ l <- matrix(list(1,2)) ; l[[4]] <- NULL ; l }"); - assertEval("{ f <- function(b,i,v) { b[[i]] <- v ; b } ; f(list(1,2,list(3)), c(3,1), 4) ; f(c(1,2,3), 2L, NULL) }"); + assertEval(Ignored.Unstable, "{ f <- function(b,i,v) { b[[i]] <- v ; b } ; f(list(1,2,list(3)), c(3,1), 4) ; f(c(1,2,3), 2L, NULL) }"); } @Test @@ -2363,5 +2363,9 @@ public class TestSimpleVectors extends TestBase { assertEval("{ x<-c(1,2); f<-function() { x<-c(100, 200); x[1]<-4; print(x) } ; f(); x }"); assertEval("{ x<-c(1,2); f<-function() { x<-c(100, 200); x[1]<<-4; print(x) } ; f(); x }"); + assertEval("{ x<-quote(foo(42)); x[character(0)]<-list(); typeof(x) }"); + assertEval("{ x<-as.pairlist(list(7,42)); x[character(0)]<-list(); typeof(x) }"); + assertEval("{ x<-expression(y, z, 7 + 42); x[character(0)]<-list(); typeof(x) }"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestChannels.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestChannels.java index 31fb033fde9bcc41309ab36cd91dab4bf010042b..86c316ebabbdc06ae6a7d8456d2591e417e03861 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestChannels.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestChannels.java @@ -22,6 +22,8 @@ */ package com.oracle.truffle.r.test.library.fastr; +import org.junit.Test; + import com.oracle.truffle.r.test.TestRBase; public class TestChannels extends TestRBase { @@ -30,4 +32,12 @@ public class TestChannels extends TestRBase { public String getTestDir() { return "channels"; } + + /** + * Needs to include a dummy test, otherwise JUnit does not pick it up for execution. + */ + @Test + public void dummyTest() { + assertEval("42"); + } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..4633fbe6cea36712abcfa82e76de810cfd1160d8 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015, 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.test.library.fastr; + +import org.junit.Test; + +import com.oracle.truffle.api.interop.java.JavaInterop; +import com.oracle.truffle.api.vm.PolyglotEngine; +import com.oracle.truffle.r.test.TestBase; + +public class TestInterop extends TestBase { + + @Test + public void testInteropEval() { + assertEvalFastR(".fastr.interop.eval('application/x-r', '14 + 2')", "16"); + assertEvalFastR(".fastr.interop.eval('application/x-r', '1')", "1"); + assertEvalFastR(".fastr.interop.eval('application/x-r', '1L')", "1L"); + assertEvalFastR(".fastr.interop.eval('application/x-r', 'TRUE')", "TRUE"); + assertEvalFastR(".fastr.interop.eval('application/x-r', 'as.character(123)')", "as.character(123)"); + } + + @Test + public void testInteropExport() { + assertEvalFastR(".fastr.interop.export('foo', 14 + 2)", "invisible()"); + assertEvalFastR(".fastr.interop.export('foo', 'foo')", "invisible()"); + assertEvalFastR(".fastr.interop.export('foo', 1:100)", "invisible()"); + assertEvalFastR(".fastr.interop.export('foo', new.env())", "invisible()"); + } + + /** + * Used for testing interop functionality. + */ + public static final class POJO { + public int intValue = 1; + public long longValue = 123412341234L; + public char charValue = 'R'; + public short shortValue = -100; + public boolean booleanValue = true; + public String stringValue = "foo"; + } + + private static final class TestJavaObject { + public final String name; + public Object object; + + private TestJavaObject(String name, Object object) { + this.name = name; + this.object = object; + } + } + + private static final TestJavaObject[] testJavaObjects = new TestJavaObject[]{new TestJavaObject("testPOJO", new POJO()), new TestJavaObject("testIntArray", new int[]{1, -5, 199}), + new TestJavaObject("testStringArray", new String[]{"a", "", "foo"})}; + + @Override + public void addPolyglotSymbols(PolyglotEngine.Builder builder) { + for (TestJavaObject t : TestInterop.testJavaObjects) { + builder.globalSymbol(t.name, JavaInterop.asTruffleObject(t.object)); + } + } + + @Test + public void testPrinting() { + assertEvalFastR("v <- .fastr.interop.import('testPOJO'); print(v)", "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" + + "\\n" + + "attr(,\"is.truffle.object\")\\n" + + "[1] TRUE\\n')"); + assertEvalFastR("v <- .fastr.interop.import('testStringArray'); print(v)", "cat('[1] \"a\" \"\" \"foo\"\\n" + + "attr(,\"is.truffle.object\")\\n" + + "[1] TRUE\\n')"); + assertEvalFastR("v <- .fastr.interop.import('testIntArray'); print(v)", "cat('[1] 1 -5 199\\n" + + "attr(,\"is.truffle.object\")\\n" + + "[1] TRUE\\n')"); + assertEvalFastR("v <- .fastr.interop.import('testIntArray'); v", "cat('[1] 1 -5 199\\n" + + "attr(,\"is.truffle.object\")\\n" + + "[1] TRUE\\n')"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestUpdateForm.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestUpdateForm.java new file mode 100644 index 0000000000000000000000000000000000000000..03fc6a7f434da9914635d112ba88fa96a7193891 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestUpdateForm.java @@ -0,0 +1,43 @@ +/* + * 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.test.library.stats; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +/** + * Tests the updateform external function called from R function update.formula, in FastR this + * function is implemented in R code. See file modelTests.R in the same directory for pure R tests + * testing only the FastR R code without the R wrappers from GnuR. When adding new test cases here, + * consider adding them to modelTests.R too. + */ +public class TestUpdateForm extends TestBase { + private static final String[] OLD_FORMULAE = new String[]{"x ~ y", ". ~ u+v", "x ~ u+v"}; + private static final String[] NEW_FORMULAE = new String[]{"~ . + x2", "log(.) ~ .:q", "x + . ~ y:. + log(.)"}; + + @Test + public void basicTests() { + assertEval(template("update.formula(%0, %1)", OLD_FORMULAE, NEW_FORMULAE)); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/modelTests.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/modelTests.R index 6fad3bc8dbd278793259a4daa352a4f4e6a0e757..d4458943fbd3bca915de0cec2cdb928819cd8a22 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/modelTests.R +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/modelTests.R @@ -32,27 +32,48 @@ # IMPORTANT: some test cases from this file are used in Java unit tests in TestFormulae # class, please update them accordingly when updating this file. -# create patched versions of R stubs for externals: -# we replace call to .External with call to our implementation -body <- deparse(model.frame.default) -idx <- which(grepl(".External2", body)) -body[[idx]] <- gsub("C_modelframe,", "", gsub(".External2", "modelframe", body[[idx]])) -modelframedefault <- eval(parse(text=body)) - -body <- deparse(model.matrix.default) -idx <- which(grepl(".External2", body)) -body[[idx]] <- gsub("C_modelmatrix,", "", gsub(".External2", "modelmatrix", body[[idx]])) -modelmatrixdefault <- eval(parse(text=body)) +gsubVec <- function(pattern, replace, text) { + for (i in seq_along(pattern)) { + text <- gsub(pattern[[i]], replace[[i]], text); + } + text +} + +saved <- list() +saveArgs <- function(...) { + saved <<- list(...) +} + +replaceExternalWithSaveArgs <- function(func, externalType='.External2') { + body <- deparse(func) + idx <- which(grepl(externalType, body)) + body[[idx]] <- gsubVec(c('C_[^,]*,', externalType), c("", "saveArgs"), body[[idx]]) + eval(parse(text=body)) +} + +# stubs that save original arguments to .External calls so that we can call them with these args by hand +# note: there is no logic in terms.formula executed before the .External call +saveArgs.model.frame.default <- replaceExternalWithSaveArgs(model.frame.default) +saveArgs.model.matrix.default <- replaceExternalWithSaveArgs(model.matrix.default) # check function compares the results +failedTests <- 0 +successTests <- 0 check <- function(expected, actual, name) { - if (try(identical(expected, actual)) != TRUE) { - cat(name, ": FAIL\n") - print(expected) - cat("\n>>>>>>>>>actual:\n\n") - print(actual) - } - else { cat(name, ": OK\n") } + if (try(identical(expected, actual)) != TRUE) { + failedTests <<- failedTests + 1 + cat(name, ": FAIL expected:\n\n") + print(expected) + cat("\n>>>>>>>>>actual:\n\n") + print(actual) + cat("\n-------------\n") + if (failedTests > 10) { + stop("Too many failed tests...") + } + } else { + successTests <<- successTests + 1 + cat(".") + } } # tests data: formulae @@ -65,24 +86,28 @@ tests <- c(tests, ignoremm) run.tests <- function() { for (t in tests) { - print(t) - check(terms.formula(t), termsform(t, NULL, NULL, FALSE, FALSE), "termsform") - - # modelframe - if (!(c(t) %in% ignoremf)) { - mf <- model.frame.default(t) - check(mf, modelframedefault(t), "model.frame.default") - } else { - next - } - - # modelmatrix - if (!(c(t) %in% ignoremm)) { - our <- modelmatrixdefault(mf) - mode(our) <- "double" # GnuR has always double results, even when not necessary - check(model.matrix.default(mf), our, "model.matrix.default") - # for one off testing: modelmatrixdefault(model.frame.default(t)) - } + print(t) + check(.External(stats:::C_termsform, t, NULL, NULL, FALSE, FALSE), termsform(t, NULL, NULL, FALSE, FALSE), "termsform") + + # modelframe + if (!(c(t) %in% ignoremf)) { + saveArgs.model.frame.default(t) + their <- do.call(.External2, c(list(stats:::C_modelframe), saved)) + ours <- do.call(modelframe, saved) + check(their, ours, "model.frame.default") + } else { + next + } + + # modelmatrix + if (!(c(t) %in% ignoremm)) { + mf <- model.frame.default(t) + saveArgs.model.matrix.default(mf) + their <- do.call(.External2, c(list(stats:::C_modelmatrix), saved)) + ours <- do.call(modelmatrix, saved) + mode(ours) <- "double" # GnuR has always double results, even when not necessary + check(their, ours, "model.matrix.default") + } } } @@ -103,20 +128,50 @@ run.tests() # check subsetting print(y~z) -mf <- model.frame.default(y~z, subset=3:7) -check(mf, modelframedefault(y~z, subset=3:7), "model.frame.default with subset") +saveArgs.model.frame.default(y~z, subset=3:7) +their <- do.call(.External2, c(list(stats:::C_modelframe), saved)) +ours <- do.call(modelframe, saved) +check(their, ours, "model.frame.default with subset") # check specials t <- y~myfun(z)+x print(t) -check(terms.formula(t, c('myfun')), termsform(t, c('myfun'), NULL, FALSE, FALSE), "termsform with specials") +check(.External(stats:::C_termsform, t, c('myfun'), NULL, FALSE, FALSE), termsform(t, c('myfun'), NULL, FALSE, FALSE), "termsform with specials") # check expand dots t <- cyl~hp*mpg+. print(t) -check(terms.formula(t, data=mtcars), termsform(t, NULL, mtcars, FALSE, FALSE), "termsform with expandDots") +check(.External(stats:::C_termsform, t, NULL, mtcars, FALSE, FALSE), termsform(t, NULL, mtcars, FALSE, FALSE), "termsform with expandDots") # check specials and expand dots t <- cyl~mufun(mpg)+. print(t) -check(terms.formula(t, specials=c('myfun'), data=mtcars), termsform(t, c('myfun'), mtcars, FALSE, FALSE), "termsform with specials and expandDots") +check(.External(stats:::C_termsform, t, c('myfun'), mtcars, FALSE, FALSE), termsform(t, c('myfun'), mtcars, FALSE, FALSE), "termsform with specials and expandDots") + + +# ------------------------------------ +# tests for update formula + +body <- deparse(update.formula) +idx <- which(grepl(".Call", body)) +body[[idx]] <- gsub("C_updateform,", "", gsub(".Call", "updateform", body[[idx]])) +updateformula <- eval(parse(text=body)) + +test.update.formula <- function(old, new) { + print(old); + print(new); + check(update.formula(old, new), updateformula(old, new), "update.formula test") +} + +test.update.formula(y ~ x, ~ . + x2) +test.update.formula(y ~ x, log(.) ~ . ) +test.update.formula(. ~ u+v, res ~ . ) +test.update.formula(~ u+v, res ~ . ) +test.update.formula(~ u+v, ~ . ) +test.update.formula(~ u+v, . ~ . ) +test.update.formula(~ u+v, ~ x*. ) +test.update.formula(~ u+v, ~ x:. ) + + +cat("\n\nFinished\nsuccessful:", successTests, "\nfailed:", failedTests) + 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 new file mode 100644 index 0000000000000000000000000000000000000000..bc17a53675c0835d35dd2890716885b057e9656a --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java @@ -0,0 +1,42 @@ +/* + * 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.test.library.utils; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestTypeConvert extends TestBase { + @Test + public void basicTests() { + assertEval("type.convert('42')"); + assertEval("type.convert(c('42', '42.42'))"); // convert to double vector + assertEval("type.convert(c('NA', 'NA'))"); + assertEval("type.convert(c('NA', 'TRUE'))"); + assertEval("type.convert(c('NA', '42'))"); + assertEval("type.convert(c('NA', '44.5'))"); + assertEval("type.convert(c(NA, '44.5'))"); // string NA + // looks like integer, but is double (because it would be INT_NA) + assertEval("type.convert('-2147483648')"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestWriteTable.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestWriteTable.java new file mode 100644 index 0000000000000000000000000000000000000000..c2bdd2d59866c234ed1fb734e45341aea4a95928 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestWriteTable.java @@ -0,0 +1,41 @@ +/* + * 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.test.library.utils; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestWriteTable extends TestBase { + @Test + public void testValuesFormatting() { + assertEval("write.csv(data.frame(double=1231231234.5, bool=TRUE, raw=as.raw(42)))"); + assertEval("write.csv(data.frame(col=as.factor(c('m', 'm', 'f', 'm'))))"); + + } + + @Test + public void testTable() { + assertEval("write.table(data.frame(col=c(1,2,3,4), col2=c(T, F, T, F)))"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestUserRNG.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestUserRNG.java index 9714a5f6b110de1242259ca185d3e5eaf80ae94b..087722ae5f5701a6944ddad2732d191b904f1bbb 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestUserRNG.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestUserRNG.java @@ -27,7 +27,6 @@ import java.nio.file.Paths; import org.junit.Test; -import com.oracle.truffle.r.runtime.REnvVars; import com.oracle.truffle.r.runtime.ffi.UserRngRFFI; import com.oracle.truffle.r.test.TestBase; @@ -39,9 +38,7 @@ import com.oracle.truffle.r.test.TestBase; public class TestUserRNG extends TestBase { @Test public void testUserRNG() { - Path cwd = Paths.get(System.getProperty("user.dir")); - Path libPath = Paths.get(REnvVars.rHome(), "com.oracle.truffle.r.test.native/urand/lib/liburand.so"); - Path relLibPath = cwd.relativize(libPath); - assertEval(TestBase.template("{ dyn.load(\"%0\"); RNGkind(\"user\"); print(RNGkind()); set.seed(4567); runif(10) }", new String[]{relLibPath.toString()})); + Path libPath = TestBase.getNativeProjectFile(Paths.get("urand", "lib", "liburand.so")); + assertEval(TestBase.template("{ dyn.load(\"%0\"); RNGkind(\"user\"); print(RNGkind()); set.seed(4567); runif(10) }", new String[]{libPath.toString()})); } } 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 index 5469875ee7b6f7771da19fc64c1106d9ca86e171..c4c4d3b6bcf7b4b15f023cf46e04601eaed2620e 100644 --- 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 @@ -22,19 +22,16 @@ */ package com.oracle.truffle.r.test.rpackages; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; -import com.oracle.truffle.r.runtime.FastROptions; +import org.junit.Assert; + import com.oracle.truffle.r.runtime.REnvVars; -import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.RVersionNumber; +import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.test.TestBase; /** @@ -60,69 +57,18 @@ import com.oracle.truffle.r.test.TestBase; */ public abstract class TestRPackages extends TestBase { - /** - * Create {@link Path}s to needed folders. - * - */ - protected static final class PackagePaths { + private static final String SYSTEM2_COMMAND = "system2('%s', c('CMD', 'INSTALL', '%s'), env='R_LIBS=%s', stdout=T, stderr=T)"; + + private static final class PackagePath { /** * The path containing the package distributions as tar files. */ - private final Path packagePath; + private final Path path; - private PackagePaths(Path rpackagesDists) { - this.packagePath = rpackagesDists; + private PackagePath(Path path) { + this.path = path; } - protected boolean installPackage() { - String[] cmds = new String[4]; - if (generatingExpected()) { - // use GnuR - cmds[0] = "R"; - } else { - // use FastR - cmds[0] = FileSystems.getDefault().getPath(REnvVars.rHome(), "bin", "R").toString(); - } - cmds[1] = "CMD"; - cmds[2] = "INSTALL"; - cmds[cmds.length - 1] = packagePath.toString(); - ProcessBuilder pb = new ProcessBuilder(cmds); - Map<String, String> env = pb.environment(); - env.put("R_LIBS", installDir().toString()); - if (!generatingExpected()) { - env.put("R_INSTALL_TAR", RContext.getInstance().stateREnvVars.get("TAR")); - } - try { - if (FastROptions.debugMatches("TestRPackages")) { - pb.inheritIO(); - } - pb.redirectErrorStream(true); - Process install = pb.start(); - BufferedReader out = new BufferedReader(new InputStreamReader(install.getInputStream(), StandardCharsets.UTF_8)); - StringBuilder str = new StringBuilder(); - try { - String line; - while ((line = out.readLine()) != null) { - str.append(line).append('\n'); - if (str.length() > 10 * (1 << 20)) { // if larger than 10M (just in case) - System.out.println(str); - str.setLength(0); // Reset buffer - } - } - } catch (IOException e) { - e.printStackTrace(); - } - int rc = install.waitFor(); - if (rc == 0) { - return true; // Ignore output of process on success - } else { - System.out.println(str); // Print if error happened - return false; - } - } catch (Exception ex) { - return false; - } - } } /** @@ -133,11 +79,11 @@ public abstract class TestRPackages extends TestBase { /** * Map from package name to info on its location. */ - private static final Map<String, PackagePaths> packageMap = new HashMap<>(); + private static final Map<String, PackagePath> packageMap = new HashMap<>(); private static Path installDir() { if (installDir == null) { - installDir = TestBase.relativize(Paths.get(REnvVars.rHome(), "com.oracle.truffle.r.test", "rpackages", "testrlibs_user")); + installDir = TestBase.createTestDir("com.oracle.truffle.r.test.rpackages"); } return installDir; } @@ -150,8 +96,7 @@ public abstract class TestRPackages extends TestBase { Path packageDir = installDir().resolve(packageName); try { deleteDir(packageDir); - } catch (Exception e) { - e.printStackTrace(); + } catch (Throwable e) { return false; } return true; @@ -167,13 +112,14 @@ public abstract class TestRPackages extends TestBase { } private static Path testNativePath() { - return Paths.get(REnvVars.rHome(), "com.oracle.truffle.r.test.native", "packages"); + Path p = TestBase.getNativeProjectFile(Paths.get("packages")); + return p; } - private static PackagePaths getPackagePaths(String pkg, Path path) { - PackagePaths result = packageMap.get(pkg); + private static PackagePath getPackagePaths(String pkg, Path path) { + PackagePath result = packageMap.get(pkg); if (result == null) { - result = new PackagePaths(path); + result = new PackagePath(path); packageMap.put(pkg, result); } return result; @@ -183,6 +129,42 @@ public abstract class TestRPackages extends TestBase { setupInstallTestPackages(testPackages, new Resolver()); } + 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 { + Object result = evalInstallPackage(String.format(SYSTEM2_COMMAND, cmd, packagePath.path.toString(), installDir().toString())); + boolean success; + if (generatingExpected()) { + String stringResult = (String) result; + success = stringResult.contains("* DONE ("); + if (!success) { + System.out.println(stringResult); + } + } else { + RStringVector vecResult = (RStringVector) result; + success = vecResult.getAttr("status") == null; + if (!success) { + String[] output = vecResult.getDataWithoutCopying(); + for (String line : output) { + System.out.println(line); + } + } + } + return success; + } catch (Throwable t) { + return false; + } + } + protected static void setupInstallTestPackages(String[] testPackages, Resolver resolver) { if (!checkOnly()) { TestBase.deleteDir(installDir()); @@ -191,9 +173,9 @@ public abstract class TestRPackages extends TestBase { for (String p : testPackages) { // Takes time, provide user feedback System.out.printf(".pkg: %s.", p); - PackagePaths packagePaths = getPackagePaths(p, resolver.getPath(p)); - if (!packagePaths.installPackage()) { - throw new AssertionError(); + PackagePath packagePath = getPackagePaths(p, resolver.getPath(p)); + if (!installPackage(packagePath)) { + Assert.fail(String.format("package %s failed to install", p)); } } System.out.printf(".end install."); @@ -204,7 +186,7 @@ public abstract class TestRPackages extends TestBase { if (!checkOnly()) { for (String p : testPackages) { if (!uninstallPackage(p)) { - throw new AssertionError(); + System.err.println("WARNING: error deleting package: " + p); } } } 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 index 805565cf8225137ee12af9ceed4fc19cf296a6cc..5cdd7ea59df3fc6cf227f961b9ecd139ebccfe44 100644 --- 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 @@ -29,41 +29,59 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; -import com.oracle.truffle.r.runtime.REnvVars; -import com.oracle.truffle.r.runtime.RVersionNumber; 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 { - private static final String[] OK_PACKAGES = new String[]{"MASS", "boot", "class", "cluster", "codetools", "lattice", "nnet", "spatial", "survival", "KernSmooth", "Matrix", "foreign", "nlme", + private static final String[] DEFAULT_PACKAGES = new String[]{"MASS", "boot", "class", "cluster", "codetools", "lattice", "nnet", "spatial", "survival", "KernSmooth", "Matrix", "foreign", "nlme", "rpart"}; - @SuppressWarnings("unused") private static final String[] PROBLEM_PACKAGES = new String[]{}; + private static String[] packages = DEFAULT_PACKAGES; - private static Path getRecommendedPath() { - return Paths.get(REnvVars.rHome(), "com.oracle.truffle.r.native", "gnur", RVersionNumber.R_HYPHEN_FULL, "src", "library", "Recommended"); + /** + * 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(OK_PACKAGES, new Resolver() { + setupInstallTestPackages(packages, new Resolver() { @Override Path getPath(String p) { - return getRecommendedPath().resolve(p + ".tgz"); + return TestBase.getNativeProjectFile(Paths.get("packages")).resolve("recommended").resolve(p + ".tgz"); } }); } @AfterClass public static void tearDownUninstallMyTestPackages() { - tearDownUninstallTestPackages(OK_PACKAGES); + tearDownUninstallTestPackages(packages); } @Test public void testLoad() { - assertEval(Context.NonShared, Context.LongTimeout, TestBase.template("{ library(%1, lib.loc = \"%0\"); detach(\"package:%1\"); }", new String[]{TestRPackages.libLoc()}, OK_PACKAGES)); + // 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/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java index 318c667e9affa52073115f643799afd861e7c6d8..d8a04e48887dd7d5328d1f2abc712dec20ded2b3 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 @@ -37,24 +37,22 @@ import org.junit.Before; import org.junit.Test; import com.oracle.truffle.api.debug.Debugger; -import com.oracle.truffle.api.debug.ExecutionEvent; import com.oracle.truffle.api.debug.SuspendedEvent; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.MaterializedFrame; -import com.oracle.truffle.api.source.LineLocation; import com.oracle.truffle.api.source.Source; -import com.oracle.truffle.api.vm.EventConsumer; 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.data.RPromise.EagerPromiseBase; +@SuppressWarnings("deprecation") public class FastRDebugTest { private Debugger debugger; private final LinkedList<Runnable> run = new LinkedList<>(); private SuspendedEvent suspendedEvent; private Throwable ex; - private ExecutionEvent executionEvent; + private com.oracle.truffle.api.debug.ExecutionEvent executionEvent; protected PolyglotEngine engine; protected final ByteArrayOutputStream out = new ByteArrayOutputStream(); protected final ByteArrayOutputStream err = new ByteArrayOutputStream(); @@ -63,22 +61,23 @@ public class FastRDebugTest { public void before() { suspendedEvent = null; executionEvent = null; - engine = PolyglotEngine.newBuilder().setOut(out).setErr(err).onEvent(new EventConsumer<ExecutionEvent>(ExecutionEvent.class) { - @Override - protected void on(ExecutionEvent event) { - executionEvent = event; - debugger = executionEvent.getDebugger(); - performWork(); - executionEvent = null; - } - }).onEvent(new EventConsumer<SuspendedEvent>(SuspendedEvent.class) { - @Override - protected void on(SuspendedEvent event) { - suspendedEvent = event; - performWork(); - suspendedEvent = null; - } - }).build(); + engine = PolyglotEngine.newBuilder().setOut(out).setErr(err).onEvent( + new com.oracle.truffle.api.vm.EventConsumer<com.oracle.truffle.api.debug.ExecutionEvent>(com.oracle.truffle.api.debug.ExecutionEvent.class) { + @Override + protected void on(com.oracle.truffle.api.debug.ExecutionEvent event) { + executionEvent = event; + debugger = executionEvent.getDebugger(); + performWork(); + executionEvent = null; + } + }).onEvent(new com.oracle.truffle.api.vm.EventConsumer<SuspendedEvent>(SuspendedEvent.class) { + @Override + protected void on(SuspendedEvent event) { + suspendedEvent = event; + performWork(); + suspendedEvent = null; + } + }).build(); run.clear(); } @@ -129,7 +128,7 @@ public class FastRDebugTest { try { assertNull(suspendedEvent); assertNotNull(executionEvent); - LineLocation nMinusOne = factorial.createLineLocation(9); + com.oracle.truffle.api.source.LineLocation nMinusOne = factorial.createLineLocation(9); debugger.setLineBreakpoint(0, nMinusOne, false); executionEvent.prepareContinue(); } catch (IOException e) { @@ -265,7 +264,7 @@ public class FastRDebugTest { Assert.assertEquals(code, actualCode); final MaterializedFrame frame = suspendedEvent.getFrame(); - Assert.assertEquals(expectedFrame.length / 2, frame.getFrameDescriptor().getSize()); + Assert.assertEquals(expectedFrame.length / 2, frameSize(frame)); for (int i = 0; i < expectedFrame.length; i = i + 2) { final String expectedIdentifier = (String) expectedFrame[i]; @@ -277,6 +276,16 @@ public class FastRDebugTest { } run.removeFirst().run(); } + + private int frameSize(MaterializedFrame frame) { + int cnt = 0; + for (FrameSlot slot : frame.getFrameDescriptor().getSlots()) { + if (slot.getIdentifier() instanceof String) { + cnt++; + } + } + return cnt; + } }); } 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 052bb9952ff78faedf34362eadf9de5d9464a11f..e8b14d8fe62005c4714bd2b54f68223ae82c5797 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 @@ -44,33 +44,26 @@ public class FastRTckTest extends TruffleTCK { "fourtyTwo <- function() {\n" + " 42L\n" + "}\n" + - ".fastr.interop.export('fourtyTwo', fourtyTwo)\n" + "plus <- function(a, b) {\n" + " a + b\n" + "}\n" + - ".fastr.interop.export('plus', plus)\n" + "identity <- function(a) {\n" + " a\n" + "}\n" + - ".fastr.interop.export('identity', identity)\n" + "apply <- function(f) {\n" + " f(18L, 32L) + 10L\n" + "}\n" + - ".fastr.interop.export('apply', apply)\n" + "null <- function() {\n" + " NULL\n" + "}\n" + - ".fastr.interop.export('null', null)\n" + "counter <- 0L\n" + "count <- function() {\n" + " counter <<- counter + 1L\n" + "}\n" + - ".fastr.interop.export('count', count)\n" + "complexAdd <- function(a, b) {\n" + " a$imaginary <- a$imaginary + b$imaginary\n" + " a$real <- a$real + b$real\n" + "}\n" + - ".fastr.interop.export('complexAdd', complexAdd)\n" + "countUpWhile <- function(fn) {\n" + " counter <- 0\n" + " while (T) {\n" + @@ -80,7 +73,6 @@ public class FastRTckTest extends TruffleTCK { " counter <- counter + 1\n" + " }\n" + "}\n" + - ".fastr.interop.export('countUpWhile', countUpWhile)\n" + "complexSumReal <- function(a) {\n" + " sum <- 0\n" + " for (i in 1:length(a)) {\n" + @@ -88,18 +80,61 @@ public class FastRTckTest extends TruffleTCK { " }\n" + " return(sum)\n" + "}\n" + - ".fastr.interop.export('complexSumReal', complexSumReal)\n" + "complexCopy <- function(a, b) {\n" + " for (i in 0:(length(b)-1)) {\n" + " a[i]$real <- b[i]$real\n" + " a[i]$imaginary <- b[i]$imaginary\n" + " }\n" + "}\n" + - ".fastr.interop.export('complexCopy', complexCopy)\n" + "valuesObject <- function() {\n" + " list('byteValue'=0L, 'shortValue'=0L, 'intValue'=0L, 'longValue'=0L, 'floatValue'=0, 'doubleValue'=0, 'charValue'=48L, 'stringValue'='', 'booleanValue'=FALSE)\n" + "}\n" + - ".fastr.interop.export('valuesObject', valuesObject)\n", + "addNumbersFunction <- function() {\n" + + " function(a, b) a + b\n" + + "}\n" + + "objectWithValueProperty <- function() {\n" + + " list(value = 42L)\n" + + "}\n" + + "callFunction <- function(f) {\n" + + " f(41L, 42L)\n" + + "}\n" + + "objectWithElement <- function(f) {\n" + + " c(0L, 0L, 42L, 0L)\n" + + "}\n" + + "objectWithValueAndAddProperty <- function(f) {\n" + + " e <- new.env()\n" + + " e$value <- 0L\n" + + " e$add <- function(inc) { e$value <- e$value + inc; e$value }\n" + + " e\n" + + "}\n" + + "callMethod <- function(f) {\n" + + " f(41L, 42L)\n" + + "}\n" + + "readElementFromForeign <- function(f) {\n" + + " f[[3L]]\n" + + "}\n" + + "writeElementToForeign <- function(f) {\n" + + " f[[3L]] <- 42L\n" + + "}\n" + + "readValueFromForeign <- function(o) {\n" + + " o$value\n" + + "}\n" + + "writeValueToForeign <- function(o) {\n" + + " o$value <- 42L\n" + + "}\n" + + "getSizeOfForeign <- function(o) {\n" + + " length(o)\n" + + "}\n" + + "isNullOfForeign <- function(o) {\n" + + " .fastr.interop.toBoolean(.fastr.interop.isNull(o))\n" + + "}\n" + + "hasSizeOfForeign <- function(o) {\n" + + " .fastr.interop.toBoolean(.fastr.interop.hasSize(o))\n" + + "}\n" + + "isExecutableOfForeign <- function(o) {\n" + + " .fastr.interop.toBoolean(.fastr.interop.isExecutable(o))\n" + + "}\n" + + "for (name in ls()) .fastr.interop.export(name, get(name))\n", RSource.Internal.TCK_INIT ); // @formatter:on @@ -186,32 +221,92 @@ public class FastRTckTest extends TruffleTCK { } @Override - public void readWriteBooleanValue() throws Exception { - // TODO not yet supported + protected String getSizeOfForeign() { + return "getSizeOfForeign"; } @Override - public void readWriteDoubleValue() throws Exception { - // TODO not yet supported + protected String isNullForeign() { + return "isNullOfForeign"; } @Override - public void readWriteCharValue() throws Exception { + protected String hasSizeOfForeign() { + return "hasSizeOfForeign"; + } + + @Override + protected String isExecutableOfForeign() { + return "isExecutableOfForeign"; + } + + @Override + protected String readValueFromForeign() { + return "readValueFromForeign"; + } + + @Override + protected String writeValueToForeign() { + return "writeValueToForeign"; + } + + @Override + protected String callFunction() { + return "callFunction"; + } + + @Override + protected String objectWithElement() { + return "objectWithElement"; + } + + @Override + protected String objectWithValueAndAddProperty() { + return "objectWithValueAndAddProperty"; + } + + @Override + protected String callMethod() { + return "callMethod"; + } + + @Override + protected String readElementFromForeign() { + return "readElementFromForeign"; + } + + @Override + protected String writeElementToForeign() { + return "writeElementToForeign"; + } + + @Override + protected String objectWithValueProperty() { + return "objectWithValueProperty"; + } + + @Override + protected String functionAddNumbers() { + return "addNumbersFunction"; + } + + @Override + public void readWriteBooleanValue() throws Exception { // TODO not yet supported } @Override - public void readWriteShortValue() throws Exception { + public void readWriteCharValue() throws Exception { // TODO not yet supported } @Override - public void readWriteByteValue() throws Exception { + public void readWriteShortValue() throws Exception { // TODO not yet supported } @Override - public void readWriteIntValue() throws Exception { + public void readWriteByteValue() throws Exception { // TODO not yet supported } @@ -356,6 +451,21 @@ public class FastRTckTest extends TruffleTCK { // TODO determine the semantics of assignments to a[i]$b } + @Override + public void testWriteToObjectWithElement() throws Exception { + // TODO mismatch between mutable and immutable data types + } + + @Override + public void testObjectWithValueAndAddProperty() throws Exception { + // TODO mismatch between mutable and immutable data types + } + + @Override + public void testCallMethod() throws Exception { + // R does not have method calls + } + @Override public String multiplyCode(String firstName, String secondName) { return firstName + '*' + secondName; diff --git a/mx.fastr/copyrights/gnu_r_ihaka_core.copyright.star b/mx.fastr/copyrights/gnu_r_ihaka_core.copyright.star new file mode 100644 index 0000000000000000000000000000000000000000..a3fa05c1dfcb2d13478ed6059582207e0fb2e585 --- /dev/null +++ b/mx.fastr/copyrights/gnu_r_ihaka_core.copyright.star @@ -0,0 +1,11 @@ +/* + * 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) 1998 Ross Ihaka + * Copyright (c) 1998--2012, The R Core Team + * Copyright (c) 2013, 2014, Oracle and/or its affiliates + * + * All rights reserved. + */ diff --git a/mx.fastr/copyrights/gnu_r_ihaka_core.copyright.star.regex b/mx.fastr/copyrights/gnu_r_ihaka_core.copyright.star.regex new file mode 100644 index 0000000000000000000000000000000000000000..f6aa3d2ffea7b64fd737bf54fc193fdb726a58e0 --- /dev/null +++ b/mx.fastr/copyrights/gnu_r_ihaka_core.copyright.star.regex @@ -0,0 +1 @@ +/\*\n \* This material is distributed under the GNU General Public License\n \* Version 2. You may review the terms of this license at\n \* http://www.gnu.org/licenses/gpl-2.0.html\n \*\n \* Copyright \(C\) 1998 Ross Ihaka\n \* Copyright \(c\) (?:[1-2][09][0-9][0-9]--)?[1-2][09][0-9][0-9], The R Core Team\n \* Copyright \(c\) (?:(20[0-9][0-9]), )?(20[0-9][0-9]), Oracle and/or its affiliates\n \*\n \* All rights reserved.\n \*/\n.* diff --git a/mx.fastr/copyrights/oracle.copyright.star b/mx.fastr/copyrights/oracle.copyright.star new file mode 100644 index 0000000000000000000000000000000000000000..9b3820ff682c7e96bd98e3039aa4b6a924a2b922 --- /dev/null +++ b/mx.fastr/copyrights/oracle.copyright.star @@ -0,0 +1,22 @@ +/* + * 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. + */ diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides index 64a55c761c15eabae7c9761e45cb00f34680dfbf..a320da9b757b0b923f6a4db32d79e5bbcf7c729b 100644 --- a/mx.fastr/copyrights/overrides +++ b/mx.fastr/copyrights/overrides @@ -37,6 +37,7 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/MathConstant com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/MathInit.java,gnu_r.core.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pbeta.java,gnu_r.core.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pbinom.java,gnu_r_ihaka.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pf.java,gnu_r_ihaka_core.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Pnorm.java,gnu_r_ihaka.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Qbinom.java,gnu_r_ihaka.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Qnorm.java,gnu_r_ihaka.copyright @@ -51,7 +52,7 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.jav com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java,gnu_r.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java,gnu_r.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java,gnu_r.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/WriteTable.java,gnu_r.copyright +com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java,gnu_r.copyright com.oracle.truffle.r.native/fficall/src/common/arithmetic_fastr.c,gnu_r_gentleman_ihaka.copyright com.oracle.truffle.r.native/fficall/src/common/coerce_fastr.c,gnu_r_gentleman_ihaka.copyright com.oracle.truffle.r.native/fficall/src/common/errors_fastr.c,gnu_r.core.copyright @@ -146,7 +147,7 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/G com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java,gnu_r.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java,gnu_r.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java,gnu_r.core.copyright -com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Inherits.java,purdue.copyright +com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java,purdue.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java,gnu_r.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java,purdue.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java,gnu_r_gentleman_ihaka.copyright @@ -373,7 +374,6 @@ com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exp com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_dollar_assign_dataframe.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_dollar_dataframe.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_parentasis_assign_factor.java,purdue.copyright -com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_parentasis_dataframe.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_parentasis_Date.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_parentasis_extract_parentasis_assign_factor.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_parentasis_extract_parentasis_factor.java,purdue.copyright @@ -620,6 +620,7 @@ com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_str com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strtrim.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_structure.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sub.java,purdue.copyright +com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_subset_dataframe.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_subset.java,purdue.copyright 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 diff --git a/mx.fastr/mx_copylib.py b/mx.fastr/mx_copylib.py new file mode 100644 index 0000000000000000000000000000000000000000..68cd691309bb6c37964a36a5bf9175c3e2a0acaf --- /dev/null +++ b/mx.fastr/mx_copylib.py @@ -0,0 +1,154 @@ +# +# Copyright (c) 2016, 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. +# +import os +import platform +import subprocess +import shutil +import mx + +def _darwin_extract_realpath(lib, libpath): + ''' + If libpath has a dependency on lib, return the path in the library, else None + ''' + try: + output = subprocess.check_output(['otool', '-L', libpath]) + lines = output.split('\n') + for line in lines[1:]: + if lib in line: + parts = line.split(' ') + return parts[0].strip() + return None + except subprocess.CalledProcessError: + mx.abort('copylib: otool failed') + +def _copylib(lib, libpath, target): + ''' + Just copying libxxx.so/dylib isn't sufficient as versioning is involved. + The path is likely a symlink to libxxx.so.n, for example, but what is really + important is the version that is encoded in the shared library itself. + Unfortunately getting that info is is OS specific. + ''' + if platform.system() == 'Darwin': + real_libpath = _darwin_extract_realpath(lib, libpath) + else: + try: + output = subprocess.check_output(['objdump', '-p', libpath]) + lines = output.split('\n') + for line in lines: + if 'SONAME' in line: + ix = line.find('lib' + lib) + real_libpath = os.path.join(os.path.dirname(libpath), line[ix:]) + except subprocess.CalledProcessError: + mx.abort('copylib: otool failed') + # copy both files + shutil.copy(real_libpath, target) + libpath_base = os.path.basename(libpath) + os.chdir(target) + if libpath != real_libpath: + # create a symlink + if os.path.exists(libpath_base): + os.remove(libpath_base) + os.symlink(os.path.basename(real_libpath), libpath_base) + # On Darwin we change the id to use @rpath + if platform.system() == 'Darwin': + try: + subprocess.check_call(['install_name_tool', '-id', '@rpath/' + libpath_base, libpath_base]) + except subprocess.CalledProcessError: + mx.abort('copylib: install_name_tool failed') + # TODO @rpath references within the library? + mx.log('copied ' + lib + ' library from ' + libpath + ' to ' + target) + +def copylib(args): + ''' + This supports a configuration where no explicit setting (e.g. LD_LIBRARY_PATH) is + required at runtime for the libraries that are required by FastR, e.g. pcre. + The easy case is when the libraries are already installed with the correct versions + in one of the directories, e.g./usr/lib, that is searched by default by the system linker - + in which case no configuration is required. + + Otherwise, since systems vary considerably in where such libraries are located, the general solution + is to copy libraries located in non-system locations into the FastR 'lib' directory. N.B. GNU R is + even more picky than FastR about library versions and depends on a larger set, so the local + copy embedded in FastR is built using PKG_LDFLAGS_OVERRIDE to specify the location of necessary external + libraries. However, the result of this analysis isn't captured anywhere, so we re-analyze here. + If PKG_LDFLAGS_OVERRIDE is unset, we assume the libraries are located in the system directories + and do nothing. + ''' + if os.environ.has_key('PKG_LDFLAGS_OVERRIDE'): + parts = os.environ['PKG_LDFLAGS_OVERRIDE'].split(' ') + ext = '.dylib' if platform.system() == 'Darwin' else '.so' + lib_prefix = 'lib' + args[0] + plain_libpath = lib_prefix + ext + for part in parts: + path = part.strip('"').lstrip('-L') + if os.path.exists(path): + for f in os.listdir(path): + if f.startswith(lib_prefix): + if os.path.exists(os.path.join(path, plain_libpath)): + f = plain_libpath + target_dir = args[1] + if not os.path.exists(os.path.join(target_dir, f)): + _copylib(args[0], os.path.join(path, f), args[1]) + return 0 + + mx.log(args[0] + ' not found in PKG_LDFLAGS_OVERRIDE, assuming system location') + +def updatelib(args): + ''' + If we captured a library then, on Darwin, we patch up the references + in the target library passed as argument to use @rpath. + args: + 0 directory containing library + ''' + ignore_list = ['R', 'Rblas', 'Rlapack', 'jniboot'] + + def ignorelib(name): + for ignore in ignore_list: + x = 'lib' + ignore + '.dylib' + if x == name: + return True + return False + + libdir = args[0] + cap_libs = [] + libs = [] + for lib in os.listdir(libdir): + if not '.dylib' in lib: + continue + if not os.path.islink(os.path.join(libdir, lib)): + libs.append(lib) + if ignorelib(lib) or os.path.islink(os.path.join(libdir, lib)): + continue + cap_libs.append(lib) + # for each of the libs, check whether they depend + # on any of the captured libs, @rpath the dependency if so + for lib in libs: + targetlib = os.path.join(libdir, lib) + for cap_lib in cap_libs: + try: + real_libpath = _darwin_extract_realpath(cap_lib, targetlib) + if real_libpath and not '@rpath' in real_libpath: + cmd = ['install_name_tool', '-change', real_libpath, '@rpath/' + cap_lib, targetlib] + subprocess.check_call(cmd) + except subprocess.CalledProcessError: + mx.abort('update: install_name_tool failed') diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py index 424c5057371abdfc34e6ce8c098acd2c367e6635..b3e5006c3f4e6877eb5f68204574b201264943b6 100644 --- a/mx.fastr/mx_fastr.py +++ b/mx.fastr/mx_fastr.py @@ -26,6 +26,11 @@ from argparse import ArgumentParser import mx import mx_gate import mx_fastr_pkgs +import mx_fastr_dists +from mx_fastr_dists import FastRNativeProject, FastRTestNativeProject, FastRReleaseProject #pylint: disable=unused-import +import mx_copylib +import mx_fastr_mkgramrd + import os ''' @@ -87,7 +92,13 @@ def do_run_r(args, command, extraVmArgs=None, jdk=None, **kwargs): vmArgs = ['-cp', mx.classpath(_r_command_project)] - vmArgs += _graal_options() + if 'nocompile' in kwargs: + nocompile = True + del kwargs['nocompile'] + else: + nocompile = False + + vmArgs += set_graal_options(nocompile) if extraVmArgs is None or not '-da' in extraVmArgs: # unless explicitly disabled we enable assertion checking @@ -126,7 +137,7 @@ def _sanitize_vmArgs(jdk, vmArgs): i = i + 1 return xargs -def _graal_options(nocompile=False): +def set_graal_options(nocompile=False): if _mx_graal: result = ['-Dgraal.InliningDepthError=500', '-Dgraal.EscapeAnalysisIterations=3', '-XX:JVMCINMethodSizeLimit=1000000'] if nocompile: @@ -223,12 +234,12 @@ def rembed(args, nonZeroIsFatal=True, extraVmArgs=None): run_r(args, 'rembed') def _fastr_gate_runner(args, tasks): - # Until fixed, we call Checkstyle here and limit to primary - with mx_gate.Task('Checkstyle check', tasks) as t: - if t: - if mx.checkstyle(['--primary']) != 0: - t.abort('Checkstyle warnings were found') - + ''' + The specific additional gates tasks provided by FastR: + 1. Copyright check + 2. Check that ExpectedTestOutput file is in sync with unit tests + 3. Unit tests + ''' # FastR has custom copyright check with mx_gate.Task('Copyright check', tasks) as t: if t: @@ -248,15 +259,18 @@ def _fastr_gate_runner(args, tasks): mx_gate.add_gate_runner(_fastr_suite, _fastr_gate_runner) +def rgate(args): + ''' + Run 'mx.gate' with given args (used in CI system). + N.B. This will fail if run without certain exclusions; use the local + 'gate' command for that. + ''' + mx_gate.gate(args) + def gate(args): - '''Run the R gate''' - # exclude findbugs until compliant + '''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 original_gate(args): - '''Run the R gate (without filtering gate tasks)''' - mx_gate.gate(args) - def _test_srcdir(): tp = 'com.oracle.truffle.r.test' return join(mx.project(tp).dir, 'src', tp.replace('.', sep)) @@ -298,10 +312,17 @@ def _junit_r_harness(args, vmArgs, jdk, junitArgs): runlistener_arg = add_arg_separator() runlistener_arg += 'gen-diff=' + args.gen_diff_output + if args.trace_tests: + runlistener_arg = add_arg_separator() + runlistener_arg += 'trace-tests' + # if args.test_methods: # runlistener_arg = add_arg_separator() # runlistener_arg = 'test-methods=' + args.test_methods + runlistener_arg = add_arg_separator() + runlistener_arg += 'test-project-output-dir=' + mx.project('com.oracle.truffle.r.test').output_dir() + # use a custom junit.RunListener runlistener = 'com.oracle.truffle.r.test.TestBase$RunListener' if len(runlistener_arg) > 0: @@ -314,7 +335,7 @@ def _junit_r_harness(args, vmArgs, jdk, junitArgs): # no point in printing errors to file when running tests (that contain errors on purpose) vmArgs += ['-DR:-PrintErrorStacktracesToFile'] - vmArgs += _graal_options(nocompile=True) + vmArgs += set_graal_options(nocompile=True) setREnvironment() @@ -329,6 +350,7 @@ def junit(args): parser.add_argument('--check-expected-output', action='store_true', help='check but do not update expected test output file') parser.add_argument('--gen-fastr-output', action='store', metavar='<path>', help='generate FastR test output file') parser.add_argument('--gen-diff-output', action='store', metavar='<path>', help='generate difference test output file ') + parser.add_argument('--trace-tests', action='store_true', help='trace the actual @Test methods as they are executed') # parser.add_argument('--test-methods', action='store', help='pattern to match test methods in test classes') if os.environ.has_key('R_PROFILE_USER'): @@ -342,6 +364,9 @@ 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) @@ -408,14 +433,11 @@ def testgen(args): except subprocess.CalledProcessError: mx.abort('RVersionNumber.main failed') - # clean the test project to invoke the test analyzer AP - testOnly = ['--projects', 'com.oracle.truffle.r.test'] - mx.clean(['--no-dist', ] + testOnly) - mx.build(testOnly) # now just invoke junit with the appropriate options mx.log("generating expected output for packages: ") for pkg in args.tests.split(','): mx.log(" " + str(pkg)) + os.environ["TZDIR"] = "/usr/share/zoneinfo/" junit(['--tests', args.tests, '--gen-expected-output', '--gen-expected-quiet']) def unittest(args): @@ -443,11 +465,18 @@ def rbdiag(args): -v Verbose output including the list of unimplemented specializations -n Ignore RNull as an argument type -m Ignore RMissing as an argument type + --mnonly Uses the RMissing and RNull values as the only samples for the chimney-sweeping + --noSelfTest Does not perform the pipeline self-test using the generated samples as the intro to each chimney-sweeping. It has no effect when --mnonly is specified as the self-test is never performed in that case. --sweep Performs the 'chimney-sweeping'. The sample combination selection method is determined automatically. - --sweep-lite Performs the 'chimney-sweeping'. The diagonal sample selection method is used. - --sweep-total Performs the 'chimney-sweeping'. The total sample selection method is used. + --sweep=lite Performs the 'chimney-sweeping'. The diagonal sample selection method is used. + --sweep=total Performs the 'chimney-sweeping'. The total sample selection method is used. + --matchLevel=same Outputs produced by FastR and GnuR must be same (default) + --matchLevel=error Outputs are considered matching if none or both outputs contain an error + --maxSweeps=N Sets the maximum number of sweeps + --outMaxLev=N Sets the maximum output detail level for report messages. Use 0 for the basic messages only. If no builtin is specified, all registered builtins are diagnosed. + An external builtin is specified by the fully qualified name of its node class. Examples: @@ -455,6 +484,7 @@ def rbdiag(args): mx rbdiag colSums colMeans -v mx rbdiag scan -m -n mx rbdiag colSums --sweep + mx rbdiag com.oracle.truffle.r.library.stats.Rnorm ''' cp = mx.classpath('com.oracle.truffle.r.nodes.test') @@ -486,22 +516,8 @@ def rcmplib(args): cp = mx.classpath([pcp.name for pcp in mx.projects_opt_limit_to_suites()]) mx.run_java(['-cp', cp, 'com.oracle.truffle.r.test.tools.cmpr.CompareLibR'] + cmpArgs) -def _cran_test_project(): - return 'com.oracle.truffle.r.test.cran' - -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') - -def _installpkgs(args, **kwargs): - script = _installpkgs_script() - return rscript([script] + args, **kwargs) +def mx_post_parse_cmd_line(opts): + mx_fastr_dists.mx_post_parse_cmd_line(opts) _commands = { 'r' : [rshell, '[options]'], @@ -509,23 +525,26 @@ _commands = { 'rscript' : [rscript, '[options]'], 'Rscript' : [rscript, '[options]'], 'rtestgen' : [testgen, ''], - 'originalgate' : [original_gate, '[options]'], + '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'], + 'rbdiag' : [rbdiag, '(builtin)* [-v] [-n] [-m] [--sweep | --sweep=lite | --sweep=total] [--mnonly] [--noSelfTest] [--matchLevel=same | --matchLevel=error] [--maxSweeps=N] [--outMaxLev=N]'], 'rcmplib' : [rcmplib, ['options']], - 'pkgtest' : [mx_fastr_pkgs.pkgtest, ['options']], 'rrepl' : [rrepl, '[options]'], 'rembed' : [rembed, '[options]'], - 'installpkgs' : [installpkgs, '[options]'], - 'installcran' : [installpkgs, '[options]'], 'r-cp' : [r_classpath, '[options]'], + 'pkgtest' : [mx_fastr_pkgs.pkgtest, ['options']], + 'installpkgs' : [mx_fastr_pkgs.installpkgs, '[options]'], + 'mkgramrd': [mx_fastr_mkgramrd.mkgramrd, '[options]'], + 'rcopylib' : [mx_copylib.copylib, '[]'], + 'rupdatelib' : [mx_copylib.updatelib, '[]'], } mx.update_commands(_fastr_suite, _commands) diff --git a/mx.fastr/mx_fastr_dists.py b/mx.fastr/mx_fastr_dists.py new file mode 100644 index 0000000000000000000000000000000000000000..1327c83963aa580df197a04e21c9d17a5a75abf8 --- /dev/null +++ b/mx.fastr/mx_fastr_dists.py @@ -0,0 +1,297 @@ +# +# Copyright (c) 2016, 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. +# +import mx +import mx_fastr +import os, string, shutil +from os.path import join + +class FastRProjectAdapter(mx.ArchivableProject): + def __init__(self, suite, name, deps, workingSets, theLicense, **args): + mx.ArchivableProject.__init__(self, suite, name, deps, workingSets, theLicense) + self.dir = join(suite.dir, name) + + def output_dir(self): + return self.dir + + def archive_prefix(self): + return "" + + def _get_files(self, d, results, filterfun=None): + for root, _, files in os.walk(join(self.dir, d)): + for f in files: + if not filterfun or filterfun(f): + 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. + 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 getResults(self): + ''' + Capture all the files from the com.oracle.truffle.r.test.native project that are needed + for running unit tests in an alternate implementation. + ''' + # plain files + 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')) + + results.append(join(self.dir, 'urand', 'lib', 'liburand.so')) + return results + +class FastRReleaseProject(FastRProjectAdapter): + ''' + Custom class for creating the FastR release project, which supports the + FASTR_RELEASE distribution. + ''' + def __init__(self, suite, name, deps, workingSets, theLicense, **args): + FastRProjectAdapter.__init__(self, suite, name, deps, workingSets, theLicense) + + def getResults(self): + results = [] + for rdir in ['bin', 'include', 'lib', 'library', 'etc', 'share', 'doc']: + self._get_files(rdir, results) + results.append(join(self.dir, 'LICENSE')) + results.append(join(self.dir, 'COPYRIGHT')) + results.append(join(self.dir, 'README.md')) + return results + + def getBuildTask(self, args): + return ReleaseBuildTask(self, args) + +class ReleaseBuildTask(mx.NativeBuildTask): + def __init__(self, project, args): + mx.NativeBuildTask.__init__(self, args, project) + + def _template(self, source, target, dictionary): + class LauncherTemplate(string.Template): + delimiter = '%%' + with open(target, "w") as targetFile: + targetFile.write(LauncherTemplate(open(source).read()).substitute(dictionary)) + + def build(self): + if os.environ.has_key('FASTR_NO_RELEASE'): + mx.log('FastR: not updating release project') + return + # copy the release directories + output_dir = self.subject.dir + fastr_dir = mx_fastr._fastr_suite.dir + for d in ['bin', 'include', 'lib', 'library', 'etc', 'share', 'doc']: + target_dir = join(output_dir, d) + if os.path.exists(target_dir): + shutil.rmtree(target_dir) + shutil.copytree(join(fastr_dir, d), target_dir) + + # copyrights + copyrights_dir = join(fastr_dir, 'mx.fastr', 'copyrights') + with open(join(output_dir, 'COPYRIGHT'), 'w') as outfile: + for copyright_file in os.listdir(copyrights_dir): + basename = os.path.basename(copyright_file) + if basename.endswith('copyright.star'): + with open(join(copyrights_dir, copyright_file)) as infile: + data = infile.read() + outfile.write(data) + # license/README + shutil.copy(join(fastr_dir, 'LICENSE'), output_dir) + shutil.copy(join(fastr_dir, 'README.md'), output_dir) + + # canonicalize R_HOME_DIR in bin/R + bin_dir = join(output_dir, 'bin') + rcmd = join(bin_dir, 'R') + # R is the generic shell script (taken essentially verbatim from GNU R) + with open(rcmd) as f: + lines = f.readlines() + with open(rcmd, 'w') as f: + for line in lines: + if line.startswith('R_HOME_DIR='): + f.write('R_HOME_DIR="$(dirname $0)/.."\n') + # produces a canonical path + line = 'R_HOME_DIR="$(unset CDPATH && cd ${R_HOME_DIR} && pwd)"\n' + f.write(line) + # jar files for the launchers + jars_dir = join(bin_dir, 'fastr_jars') + if not os.path.exists(jars_dir): + os.mkdir(jars_dir) + fastr_classfiles = dict() + + # visitor to collect/copy all the classes/jar files needed by the launchers + def dep_visit(dep, edge): + if isinstance(dep, mx.JARDistribution): + shutil.copy(join(dep.suite.dir, dep.path), jars_dir) + elif isinstance(dep, mx.Library): + jar_name = dep.name.lower() + '.jar' + shutil.copyfile(join(dep.suite.dir, dep.path), join(jars_dir, jar_name)) + elif isinstance(dep, mx.JavaProject): + if 'com.oracle.truffle.r' in dep.name: + classfiles_dir = dep.output_dir() + for root, _, classfiles in os.walk(classfiles_dir): + for classfile in classfiles: + fastr_classfiles[os.path.relpath(join(root, classfile), classfiles_dir)] = join(root, classfile) + + self.subject.walk_deps(visit=dep_visit) + + # create the fastr.jar file + with mx.Archiver(join(jars_dir, 'fastr.jar')) as arc: + arc.zf.writestr("META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n") + for arcname, path in fastr_classfiles.iteritems(): + with open(path, 'r') as f: + contents = f.read() + arc.zf.writestr(arcname, contents) + + # create the classpath string + classpath = [] + for _, _, jars in os.walk(jars_dir): + for jar in jars: + classpath.append(join("$R_HOME/bin/fastr_jars", jar)) + classpath_string = ":".join(classpath) + + # replace the mx exec scripts with native Java launchers, setting the classpath from above + bin_exec_dir = join(bin_dir, 'exec') + r_launcher = join(self.subject.dir, 'src', 'R_launcher') + template_dict = {'CLASSPATH': classpath_string} + self._template(r_launcher, join(bin_exec_dir, 'R'), template_dict) + shutil.rmtree(join(bin_dir, 'execRextras')) + rscript_launcher = join(self.subject.dir, 'src', 'Rscript_launcher') + self._template(rscript_launcher, join(bin_dir, 'Rscript'), template_dict) + +class FastRArchiveParticipant: + def __init__(self, dist): + self.dist = dist + + def __opened__(self, arc, srcArc, services): + # The release project states dependencies on the java projects in order + # to ensure they are built first. Therefore, the JarDistribution code + # will include all their class files at the top-level of the jar by default. + # Since we have already encapsulated the class files in 'fastr_jars/fastr.jar' we + # suppress their inclusion here by resetting the deps field. A bit of a hack. + if self.dist.name == "FASTR_RELEASE": + assert isinstance(self.dist.deps[0], FastRReleaseProject) + self.release_project = self.dist.deps[0] + self.dist.deps[0].deps = [] + + def __add__(self, arcname, contents): + return False + + def __addsrc__(self, arcname, contents): + return False + + def __closing__(self): + if self.dist.name == "FASTR_RELEASE": + # the files copied in can be confused as source files by + # e.g., mx copyright, so delete them, specifically thne + # include dir + include_dir = join(self.release_project.dir, 'include') + shutil.rmtree(include_dir) + + +def mx_post_parse_cmd_line(opts): + for dist in mx_fastr._fastr_suite.dists: + dist.set_archiveparticipant(FastRArchiveParticipant(dist)) diff --git a/mx.fastr/mx_fastr_mkgramrd.py b/mx.fastr/mx_fastr_mkgramrd.py new file mode 100644 index 0000000000000000000000000000000000000000..5ca3f5c4294770c6ec6badc4fd84a0233a24a1ee --- /dev/null +++ b/mx.fastr/mx_fastr_mkgramrd.py @@ -0,0 +1,133 @@ +# +# Copyright (c) 2016, 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. +# + +def mkgramrd(args): + ''' + converts GNU R gramRd.c into one suitable for invoking via FastR + ''' + parse_defs = ''' +extern SEXP R_SrcrefSymbol; +extern SEXP R_SrcfileSymbol; +extern int R_ParseContextLast; +#define R_EOF -1 +#define PARSE_ERROR_SIZE 256 +#define PARSE_CONTEXT_SIZE 256 +static char R_ParseErrorMsg[PARSE_ERROR_SIZE]; +static char R_ParseContext[PARSE_CONTEXT_SIZE]; +int R_ParseContextLast; +int R_ParseContextLine; +int R_ParseError; +extern SEXP R_EmptyEnv; +extern SEXP R_NewHashedEnv(SEXP a, SEXP b); + +char *dgettext(const char *p, const char *msgid) { +return msgid; +} + +int imax2(int x, int y) +{ + return (x < y) ? y : x; +} +''' + + connect_defs = ''' +typedef SEXP Rconnection; +static int Rconn_fgetc(Rconnection con) { + return -1; +} + +''' + + c_parserd = ''' + If there is text then that is read and the other arguments are ignored. + + This is derived fron the function of the same name in the GnuR version. + Argument checking has already been performed, however, the types of the + arguments are as per the GnuR version, just passed explicitly (.Call style) + rather then as a list. +*/ +SEXP C_parseRd(SEXP con, SEXP source, SEXP verbose, SEXP fragment, SEXP basename, SEXP warningcalls, SEXP macros, SEXP warnDupsArg) { + SEXP s = R_NilValue; + ParseStatus status; + +#if DEBUGMODE + yydebug = 1; +#endif + + R_ParseError = 0; + R_ParseErrorMsg[0] = '\\0'; + + PushState(); + +// parseState.xxDebugTokens = asInteger(verbose); + parseState.xxBasename = CHAR(STRING_ELT(basename, 0)); + wCalls = asLogical(warningcalls); + warnDups = asLogical(warnDupsArg); + + s = R_ParseRd(con, &status, source, asLogical(fragment), macros); + PopState(); + if (status != PARSE_OK) { + // TODO throw an exception + } + return s; +} + +// TODO deparseRd +''' + with open(args[0]) as f: + lines = f.readlines() + + with open(args[1], 'w') as f: + i = 0 + while i < len(lines): + line = lines[i] + sline = line.rstrip() + if sline == '#include <Defn.h>': + line = '//' + line + f.write(line) + f.write('#include <Rinternals.h>\n') + elif sline == '#include <Parse.h>': + f.write('#include <R_ext/Parse.h>\n') + elif 'bison creates a non-static symbol yylloc' in sline: + f.write(parse_defs) + f.write(line) + elif '#include <Rmath.h>' in sline: + line = '//' + line + f.write(line) + f.write('#include "gramRd_fastr.h"\n') + elif sline == '#include "Rconnections.h"': + line = '//' + line + f.write(line) + f.write(connect_defs) + elif 'c = Rconn_fgetc(con_parse);' in sline: + f.write(' c = callGetCMethod(con_parse);\n') + elif sline == 'static void con_cleanup(void *data)': + # skip + i = i + 5 + elif '.External2(C_parseRd' in sline: + f.write(line) + f.write(c_parserd) + break + else: + f.write(line) + i = i + 1 diff --git a/mx.fastr/mx_fastr_pkgs.py b/mx.fastr/mx_fastr_pkgs.py index 334b4c3e9a4b935b38cb3e0ec3e621c681c5be02..f5771fbc8b29c1146c5725547a3d42d2e71d1415 100644 --- a/mx.fastr/mx_fastr_pkgs.py +++ b/mx.fastr/mx_fastr_pkgs.py @@ -49,6 +49,40 @@ 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 _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') + +def _is_graalvm(): + return os.environ.has_key('GRAALVM_FASTR') + +def _graalvm(): + return os.environ['GRAALVM_FASTR'] + +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 + FastR, but instead have to invoke the command directly. + ''' + script = _installpkgs_script() + if _is_graalvm(): + rscript = join(_graalvm(), 'bin', 'Rscript') + return mx.run([rscript, script] + args, **kwargs) + else: + return mx_fastr.rscript([script] + args, **kwargs) + + def pkgtest(args): ''' Package installation/testing. @@ -56,7 +90,11 @@ def pkgtest(args): ''' libinstall, install_tmp = _create_libinstall(mx.suite('fastr')) - stacktrace_args = ['--J', '@-DR:-PrintErrorStacktracesToFile -DR:+PrintErrorStacktraces'] + + if _is_graalvm(): + stacktrace_args = ['-J:-DR:-PrintErrorStacktracesToFile', '-J:-DR:+PrintErrorStacktraces'] + else: + stacktrace_args = ['--J', '@-DR:-PrintErrorStacktracesToFile -DR:+PrintErrorStacktraces'] if "--quiet" in args: global quiet quiet = True @@ -133,7 +171,7 @@ def pkgtest(args): _log_step('BEGIN', 'install/test', 'FastR') # Currently installpkgs does not set a return code (in install.cran.packages.R) - rc = mx_fastr._installpkgs(stacktrace_args + install_args, nonZeroIsFatal=False, env=env, out=out, err=out) + rc = _installpkgs(stacktrace_args + install_args, nonZeroIsFatal=False, env=env, out=out, err=out) if rc == 100: # fatal error connecting to package repo mx.abort(rc) @@ -217,7 +255,7 @@ def _install_vignette_support(rvariant, env): _log_step('END', 'install vignette support', rvariant) def _gnur_installpkgs(args, env, **kwargs): - return mx.run(['Rscript', mx_fastr._installpkgs_script()] + args, env=env, **kwargs) + return mx.run(['Rscript', _installpkgs_script()] + args, env=env, **kwargs) def _gnur_install_test(pkgs): gnur_packages = join(_mx_gnur().dir, 'gnur.packages') @@ -226,9 +264,9 @@ def _gnur_install_test(pkgs): f.write(pkg) f.write('\n') # clone the cran test project into gnur - gnur_cran_test_project_dir = join(_mx_gnur().dir, mx_fastr._cran_test_project()) + gnur_cran_test_project_dir = join(_mx_gnur().dir, _cran_test_project()) if not exists(gnur_cran_test_project_dir): - shutil.copytree(mx_fastr._cran_test_project_dir(), gnur_cran_test_project_dir) + shutil.copytree(_cran_test_project_dir(), gnur_cran_test_project_dir) gnur_libinstall, gnur_install_tmp = _create_libinstall(_mx_gnur()) env = os.environ.copy() gnur = _mx_gnur().extensions diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py index bd1837a79e77c0bce1b99dd90e6a170a69d8f94d..72aadb14dfb6e0d5fb99360512035f849c73ce3b 100644 --- a/mx.fastr/suite.py +++ b/mx.fastr/suite.py @@ -28,7 +28,7 @@ suite = { "suites" : [ { "name" : "truffle", - "version" : "bd163128ec958b97ebc68b33ac5b4fae376a37b5", + "version" : "af21c6632dbc4e8c48cd25d0b7d623d379c888e6", "urls" : [ {"url" : "https://github.com/graalvm/truffle", "kind" : "git"}, {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"}, @@ -38,6 +38,13 @@ suite = { ], }, + "repositories" : { + "snapshots" : { + "url" : "https://FASTR_SNAPSHOT_HOST/nexus/content/repositories/snapshots", + "licenses" : ["GPLv2"] + } + }, + "licenses" : { "GPLv2" : { "name" : "GNU General Public License, version 2", @@ -49,7 +56,8 @@ suite = { # libraries that we depend on # N.B. The first four with a "path" attribute must be located - # relative to the suite root and not the mx cache + # relative to the suite root and not the mx cache because they are + # explicitly referenced in the Parser annotation processor. "libraries" : { "GNUR" : { "path" : "libdownloads/R-3.2.4.tar.gz", @@ -82,123 +90,6 @@ suite = { "sha1" : "ebb4b995fd67a9b291ea5b19379509160f56e154", }, - - "NETLIB" : { - "urls" : ["http://central.maven.org/maven2/com/googlecode/netlib-java/netlib-java/0.9.3/netlib-java-0.9.3.jar"], - "sha1" : "1d41b60e5180f6bcb7db15e7353dde7147cd3928", - }, - - "JNR_POSIX" : { - "urls" : [ - "https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/jnr-posix-3.0.18.jar", - "https://search.maven.org/remotecontent?filepath=com/github/jnr/jnr-posix/3.0.18/jnr-posix-3.0.18.jar", - ], - "sha1" : "96ae4f7837eeda0e47a470570da1803941f1bf78", - }, - - "JNR_CONSTANTS" : { - "urls" : [ - "https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/jnr-constants-0.9.0.jar", - "https://search.maven.org/remotecontent?filepath=com/github/jnr/jnr-constants/0.9.0/jnr-constants-0.9.0.jar", - ], - "sha1" : "6894684e17a84cd500836e82b5e6c674b4d4dda6", - }, - - "JNR_FFI" : { - "urls" : [ - "https://search.maven.org/remotecontent?filepath=com/github/jnr/jnr-ffi/2.0.7/jnr-ffi-2.0.7.jar", - ], - "sourcePath" : "https://search.maven.org/remotecontent?filepath=com/github/jnr/jnr-ffi/2.0.7/jnr-ffi-2.0.7-sources.jar", - "sha1" : "f0968c5bb5a283ebda2df3604c2c1129d45196e3", - "sourceSha1" : "164d820d7c38c14cd3675bfbf3eb6aeeedc9b0f4", - }, - - "JFFI" : { - "urls" : [ - "https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/jffi-1.2.9.jar", - "https://search.maven.org/remotecontent?filepath=com/github/jnr/jffi/1.2.9/jffi-1.2.9.jar", - ], - "sha1" : "93294973285d2977c41fb1cfcfa864d41b145498", - }, - - "JFFI_NATIVE" : { - "urls" : [ - "https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/jffi-1.2.9-native.jar", - "https://search.maven.org/remotecontent?filepath=com/github/jnr/jffi/1.2.9/jffi-1.2.9-native.jar", - ], - "sha1" : "1b1e82f867bb47237e6db690fbc6bfc999689c63", - }, - - "JNR_INVOKE" : { - "urls" : ["https://search.maven.org/remotecontent?filepath=com/github/jnr/jnr-invoke/0.1/jnr-invoke-0.1.jar"], - "sha1" : "d0f846c3d3cb98dfd5e2bbd3cca236337fb0afa1", - }, - - "JNR_UDIS86" : { - "urls" : ["https://search.maven.org/remotecontent?filepath=com/github/jnr/jnr-udis86/0.1/jnr-udis86-0.1.jar"], - "sha1" : "88accfa82203ea74a4a82237061c28ac8b4224af", - }, - - "JNR_X86ASM" : { - "urls" : [ - "https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/jnr-x86asm-1.0.2.jar", - "https://search.maven.org/remotecontent?filepath=com/github/jnr/jnr-x86asm/1.0.2/jnr-x86asm-1.0.2.jar", - ], - "sha1" : "006936bbd6c5b235665d87bd450f5e13b52d4b48", - }, - - "ASM" : { - "path" : "lib/asm-5.0.3.jar", - "urls" : [ - "http://lafo.ssw.uni-linz.ac.at/graal-external-deps/asm-5.0.3.jar", - "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm/5.0.3/asm-5.0.3.jar", - ], - "sha1" : "dcc2193db20e19e1feca8b1240dbbc4e190824fa", - "sourcePath" : "lib/asm-5.0.3-sources.jar", - "sourceSha1" : "f0f24f6666c1a15c7e202e91610476bd4ce59368", - "sourceUrls" : [ - "http://lafo.ssw.uni-linz.ac.at/graal-external-deps/asm-5.0.3-sources.jar", - "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm/5.0.3/asm-5.0.3-sources.jar", - ], - }, - - "ASM_ANALYSIS" : { - "path" : "lib/asm-analysis-4.0.jar", - "urls" : [ - "http://lafo.ssw.uni-linz.ac.at/graal-external-deps/asm-analysis-4.0.jar", - "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-analysis/4.0/asm-analysis-4.0.jar", - ], - "sha1" : "1c45d52b6f6c638db13cf3ac12adeb56b254cdd7", - }, - - "ASM_COMMONS" : { - "path" : "lib/asm-commons-4.0.jar", - "urls" : [ - "http://lafo.ssw.uni-linz.ac.at/graal-external-deps/asm-commons-4.0.jar", - "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-commons/4.0/asm-commons-4.0.jar", - ], - "sha1" : "a839ec6737d2b5ba7d1878e1a596b8f58aa545d9", - }, - - "ASM_TREE" : { - "path" : "lib/asm-tree-4.0.jar", - "urls" : [ - "http://lafo.ssw.uni-linz.ac.at/graal-external-deps/asm-tree-4.0.jar", - "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-tree/4.0/asm-tree-4.0.jar", - ], - "sha1" : "67bd266cd17adcee486b76952ece4cc85fe248b8", - }, - - "ASM_UTIL" : { - "path" : "lib/asm-util-4.0.jar", - "urls" : [ - "http://lafo.ssw.uni-linz.ac.at/graal-external-deps/asm-util-4.0.jar", - "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-util/4.0/asm-util-4.0.jar", - ], - "sha1" : "d7a65f54cda284f9706a750c23d64830bb740c39", - }, - - }, "projects" : { @@ -282,6 +173,7 @@ suite = { "com.oracle.truffle.r.test.native" : { "sourceDirs" : [], "dependencies" : ["com.oracle.truffle.r.native"], + "class" : "FastRTestNativeProject", "native" : "true", "workingSets" : "FastR", }, @@ -332,21 +224,6 @@ suite = { "sourceDirs" : ["src"], "dependencies" : [ "com.oracle.truffle.r.runtime", - "ASM", - "ASM_ANALYSIS", - "JNR_POSIX", - "ASM_UTIL", - "JFFI", - "JNR_FFI", - "NETLIB", - "JNR_CONSTANTS", - "JFFI_NATIVE", - "JNR_INVOKE", - "JNR_UDIS86", - "ASM", - "ASM_TREE", - "ASM_COMMONS", - "JNR_X86ASM", ], "checkstyle" : "com.oracle.truffle.r.runtime", "javaCompliance" : "1.8", @@ -361,8 +238,8 @@ suite = { "GNU_ICONV", ], "native" : "true", + "class" : "FastRNativeProject", "output" : "com.oracle.truffle.r.native", - "results" : ["platform.mk"], "workingSets" : "FastR", }, @@ -382,10 +259,17 @@ suite = { }, + "com.oracle.truffle.r.release" : { + "sourceDirs" : ["src"], + "dependencies" : ["com.oracle.truffle.r.engine", "com.oracle.truffle.r.runtime.ffi", "com.oracle.truffle.r.native"], + "class" : "FastRReleaseProject", + "output" : "com.oracle.truffle.r.release" + }, }, "distributions" : { "TRUFFLE_R_PARSER_PROCESSOR" : { + "description" : "internal support for generating the R parser", "subDir" : "truffle", "dependencies" : ["com.oracle.truffle.r.parser.processor"], "exclude" : [ @@ -393,28 +277,16 @@ suite = { "ANTLR-3.5", "ANTLR-C-3.5", ], + "maven" : "False", }, + "FASTR" : { + "description" : "class files for compiling against FastR in a separate suite", "dependencies" : ["com.oracle.truffle.r.engine", "com.oracle.truffle.r.runtime.ffi"], "mainClass" : "com.oracle.truffle.r.engine.shell.RCommand", "exclude" : [ "JDK_TOOLS", - "NETLIB", - "ASM", - "ASM_UTIL", - "ASM_TREE", - "ASM_COMMONS", - "ASM_ANALYSIS", - "ASM", - "JNR_X86ASM", - "JFFI_NATIVE", - "JFFI", - "JNR_FFI", - "JNR_CONSTANTS", - "JNR_POSIX", - "JNR_INVOKE", - "JNR_UDIS86", "truffle:JLINE", "ANTLR-C-3.5", "ANTLR-3.5", @@ -428,16 +300,77 @@ suite = { ], }, - "FASTR_NATIVE": { - "native" : True, - "path" : "mxbuild/dists/fastr.native.tar", + "FASTR_UNIT_TESTS" : { + "description" : "unit tests", + "dependencies" : ["com.oracle.truffle.r.test"], + "exclude": ["mx:HAMCREST", "mx:JUNIT", "mx:JMH"], + "distDependencies" : [ + "FASTR", + "truffle:TRUFFLE_API", + "truffle:TRUFFLE_DEBUG", + "TRUFFLE_R_PARSER_PROCESSOR", + "truffle:TRUFFLE_TCK", + ], + + + }, + + "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" : { + "amd64" : { + "path" : "mxbuild/dists/linux/amd64/fastr-unit-tests-native.jar", + } + }, + "darwin" : { + "amd64" : { + "path" : "mxbuild/dists/darwin/amd64/fastr-unit-tests-native.jar", + }, + }, + }, + }, + + "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", + }, + }, + "darwin" : { + "amd64" : { + "path" : "mxbuild/dists/darwin/amd64/fastr-native-dev.jar", + }, + }, + }, + }, + + "FASTR_RELEASE": { + "description" : "a binary release of FastR", + "dependencies" : ["com.oracle.truffle.r.release"], + "os_arch" : { + "linux" : { + "amd64" : { + "path" : "mxbuild/dists/linux/amd64/fastr-release.jar", + } + }, + "darwin" : { + "amd64" : { + "path" : "mxbuild/dists/darwin/amd64/fastr-release.jar", + } + }, + }, + }, }, - } +