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 7589fcf8a876b1e29552a48df8e27e5fb4ddd724..ee090e1c1ac7134433c540a1242dc2a56006ab89 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 @@ -25,7 +25,6 @@ package com.oracle.truffle.r.engine; import java.io.File; import java.util.Arrays; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; import com.oracle.truffle.api.CallTarget; @@ -78,6 +77,7 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE; import com.oracle.truffle.r.runtime.ReturnException; +import com.oracle.truffle.r.runtime.RootWithBody; import com.oracle.truffle.r.runtime.SubstituteVirtualFrame; import com.oracle.truffle.r.runtime.ThreadTimings; import com.oracle.truffle.r.runtime.Utils; @@ -99,7 +99,6 @@ 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; -import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; @@ -250,7 +249,7 @@ final class REngine implements Engine, Engine.Timings { @Override public Object parseAndEval(Source source, MaterializedFrame frame, boolean printResult) throws ParseException { - List<RSyntaxNode> list = parseImpl(null, source); + List<RSyntaxNode> list = parseImpl(source); try { Object lastValue = RNull.instance; for (RSyntaxNode node : list) { @@ -279,31 +278,21 @@ final class REngine implements Engine, Engine.Timings { } } - private static List<RSyntaxNode> parseImpl(Map<String, Object> constants, Source source) throws ParseException { + private static List<RSyntaxNode> parseImpl(Source source) throws ParseException { RParserFactory.Parser<RSyntaxNode> parser = RParserFactory.getParser(); - return parser.script(source, new RASTBuilder(constants)); + return parser.script(source, new RASTBuilder()); } @Override - public RExpression parse(Map<String, Object> constants, Source source) throws ParseException { - List<RSyntaxNode> list = parseImpl(constants, source); + public RExpression parse(Source source) throws ParseException { + List<RSyntaxNode> list = parseImpl(source); Object[] data = list.stream().map(node -> RASTUtils.createLanguageElement(node)).toArray(); return RDataFactory.createExpression(data); } - @Override - public RFunction parseFunction(Map<String, Object> constants, String name, Source source, MaterializedFrame enclosingFrame) throws ParseException { - RParserFactory.Parser<RSyntaxNode> parser = RParserFactory.getParser(); - RootCallTarget callTarget = parser.rootFunction(source, name, new RASTBuilder(constants)); - FrameSlotChangeMonitor.initializeEnclosingFrame(callTarget.getRootNode().getFrameDescriptor(), 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); + List<RSyntaxNode> statements = parseImpl(source); return Truffle.getRuntime().createCallTarget(new PolyglotEngineRootNode(statements, createSourceSection(statements))); } @@ -488,7 +477,7 @@ final class REngine implements Engine, Engine.Timings { * context of that frame. Note that passing only this one frame argument, strictly spoken, * violates the frame layout as set forth in {@link RArguments}. This is for internal use only. */ - private final class AnonymousRootNode extends RootNode { + private final class AnonymousRootNode extends RootNode implements RootWithBody { private final ValueProfile frameTypeProfile = ValueProfile.createClassProfile(); private final ConditionProfile isVirtualFrameProfile = ConditionProfile.createBinaryProfile(); @@ -578,6 +567,11 @@ final class REngine implements Engine, Engine.Timings { public boolean isCloningAllowed() { return false; } + + @Override + public RNode getBody() { + return body; + } } @TruffleBoundary 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 60b6a089028cf268afd4a74c3634019979dfcc84..7e846867c53f4cc0ea48208d559d36e5ffa49381 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 @@ -57,6 +57,7 @@ import com.oracle.truffle.r.nodes.control.ReplacementDispatchNode; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; import com.oracle.truffle.r.nodes.function.FunctionExpressionNode; import com.oracle.truffle.r.nodes.function.RCallNode; +import com.oracle.truffle.r.nodes.instrumentation.RInstrumentation; import com.oracle.truffle.r.runtime.Arguments; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RArguments; @@ -712,4 +713,9 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { public String encodeComplex(RComplex x, int digits) { return ComplexVectorPrinter.encodeComplex(x, digits); } + + @Override + public void checkDebugRequest(RFunction func) { + RInstrumentation.checkDebugRequested(func); + } } 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 2f58d2ee6581dd3cd596ea0e234e6332c6a77efa..a0885395fdbcdeb7338b92796840afd50eb0bf7f 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 @@ -55,7 +55,6 @@ 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; /** * Only does the minimum for running under the debugger. It is not completely clear how to correctly @@ -77,7 +76,6 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> { RAccuracyInfo.initialize(); RVersionInfo.initialize(); TempPathName.initialize(); - RPackageSource.initialize(); } catch (Throwable t) { t.printStackTrace(); 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 556ee1c823258e2d1ae4cecd45a75bf2194e42a6..7c28a860b7c2c9158abd41f07e4360f1753f3d26 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 @@ -41,17 +41,10 @@ import static com.oracle.truffle.r.library.stats.StatsUtil.rqp01check; 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.RExternalBuiltinNode; +import com.oracle.truffle.r.library.stats.StatsFunctions.Function3_2; 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.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.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; -import com.oracle.truffle.r.runtime.ops.na.NACheck; /** * Java implementation of the qgamma function. The logic was derived from GNU R (see inline @@ -62,39 +55,10 @@ public abstract class GammaFunctions { // This is derived from distn.c. - public abstract static class Qgamma extends RExternalBuiltinNode.Arg5 { - - private final NACheck naCheck = NACheck.create(); - - @TruffleBoundary - private RDoubleVector qgamma(RAbstractDoubleVector p, RAbstractDoubleVector shape, RAbstractDoubleVector scale, byte lowerTail, byte logP) { - int pLen = p.getLength(); - int shapeLen = shape.getLength(); - int scaleLen = scale.getLength(); - double[] result = new double[Math.max(pLen, Math.max(shapeLen, scaleLen))]; - RAbstractDoubleVector attrSource = null; - if (result.length > 1) { - attrSource = pLen == result.length ? p : (shapeLen == result.length ? shape : scale); - } - naCheck.enable(true); - for (int i = 0, l = 0, j = 0, k = 0; i < result.length; ++i, l = Utils.incMod(l, pLen), j = Utils.incMod(j, shapeLen), k = Utils.incMod(k, scaleLen)) { - double pv = p.getDataAt(l); - result[i] = GammaFunctions.qgamma(pv, shape.getDataAt(j), scale.getDataAt(k), lowerTail == RRuntime.LOGICAL_TRUE, logP == RRuntime.LOGICAL_TRUE); - naCheck.check(result[i]); - } - RDoubleVector res = RDataFactory.createDoubleVector(result, naCheck.neverSeenNA()); - if (attrSource != null) { - res.copyAttributesFrom(attrProfiles, attrSource); - } - return res; - } - - @Specialization - public RAbstractDoubleVector qgamma(RAbstractDoubleVector p, RAbstractDoubleVector shape, RAbstractDoubleVector scale, RAbstractLogicalVector lowerTail, RAbstractLogicalVector logP) { - if (shape.getLength() == 0 || scale.getLength() == 0) { - return RDataFactory.createEmptyDoubleVector(); - } - return qgamma(p, shape, scale, castLogical(lowerTail), castLogical(logP)); + public static final class QgammaFunc implements Function3_2 { + @Override + public double evaluate(double p, double shape, double scale, boolean lowerTail, boolean logP) { + return GammaFunctions.qgamma(p, shape, scale, lowerTail, logP); } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandGenerationFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandGenerationFunctions.java new file mode 100644 index 0000000000000000000000000000000000000000..25346c43a48443f7ae4532e5bfc94868e2f6fb04 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandGenerationFunctions.java @@ -0,0 +1,298 @@ +/* + * This material is distributed under the GNU General Public License + * Version 2. You may review the terms of this license at + * http://www.gnu.org/licenses/gpl-2.0.html + * + * Copyright (c) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2003-2015, The R Foundation + * 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.nodes.builtin.CastBuilder.Predef.abstractVectorValue; +import static com.oracle.truffle.r.runtime.RError.Message.INVALID_UNNAMED_ARGUMENTS; +import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; + +import java.util.Arrays; + +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.BranchProfile; +import com.oracle.truffle.api.profiles.LoopConditionProfile; +import com.oracle.truffle.r.library.stats.RandGenerationFunctionsFactory.ConvertToLengthNodeGen; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; +import com.oracle.truffle.r.nodes.unary.CastIntegerNode; +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.RDouble; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.ops.na.NACheck; +import com.oracle.truffle.r.runtime.rng.RRNG; + +public final class RandGenerationFunctions { + public static final double ERR_NA = RRuntime.DOUBLE_NA; + private static final RDouble DUMMY_VECTOR = RDouble.valueOf(1); + + private RandGenerationFunctions() { + // static class + } + + // inspired by the DEFRAND{X}_REAL and DEFRAND{X}_INT macros in GnuR + + public interface RandFunction3_Int { + int evaluate(double a, double b, double c); + } + + public interface RandFunction2_Int extends RandFunction3_Int { + @Override + default int evaluate(double a, double b, double c) { + return evaluate(a, b); + } + + int evaluate(double a, double b); + } + + public interface RandFunction2_Double { + /** + * If returns {@code false}, {@link #evaluate(double, double)} will not be invoked. + */ + boolean isValid(double a, double b); + + /** + * Is guaranteed to be preceded by invocation of {@link #isValid(double, double)} with the + * same arguments. + */ + double evaluate(double a, double b); + } + + public abstract static class RandFunction2_DoubleAdapter implements RandFunction2_Double { + public boolean isValid(double a, double b) { + return true; + } + } + + static final class RandGenerationProfiles { + final BranchProfile nanResult = BranchProfile.create(); + final BranchProfile errResult = BranchProfile.create(); + final BranchProfile nan = BranchProfile.create(); + final NACheck aCheck = NACheck.create(); + final NACheck bCheck = NACheck.create(); + final NACheck cCheck = NACheck.create(); + final VectorLengthProfile resultVectorLengthProfile = VectorLengthProfile.create(); + final LoopConditionProfile loopConditionProfile = LoopConditionProfile.createCountingProfile(); + + public static RandGenerationProfiles create() { + return new RandGenerationProfiles(); + } + } + + private static RAbstractIntVector evaluate3Int(Node node, RandFunction3_Int function, int lengthIn, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, + RandGenerationProfiles profiles) { + int length = profiles.resultVectorLengthProfile.profile(lengthIn); + int aLength = a.getLength(); + int bLength = b.getLength(); + int cLength = c.getLength(); + if (aLength == 0 || bLength == 0 || cLength == 0) { + profiles.nanResult.enter(); + RError.warning(SHOW_CALLER, RError.Message.NAN_PRODUCED); + int[] nansResult = new int[length]; + Arrays.fill(nansResult, RRuntime.INT_NA); + return RDataFactory.createIntVector(nansResult, false); + } + + RNode.reportWork(node, length); + boolean complete = true; + boolean nans = false; + profiles.aCheck.enable(a); + profiles.bCheck.enable(b); + profiles.cCheck.enable(c); + int[] result = new int[length]; + RRNG.getRNGState(); + for (int i = 0; profiles.loopConditionProfile.inject(i < length); i++) { + double aValue = a.getDataAt(i % aLength); + double bValue = b.getDataAt(i % bLength); + double cValue = c.getDataAt(i % cLength); + int value; + if (Double.isNaN(aValue) || Double.isNaN(bValue) || Double.isNaN(cValue)) { + profiles.nan.enter(); + value = RRuntime.INT_NA; + if (profiles.aCheck.check(aValue) || profiles.bCheck.check(bValue) || profiles.cCheck.check(cValue)) { + complete = false; + } + } else { + value = function.evaluate(aValue, bValue, cValue); + if (Double.isNaN(value)) { + profiles.nan.enter(); + nans = true; + } + } + result[i] = value; + } + RRNG.putRNGState(); + if (nans) { + RError.warning(SHOW_CALLER, RError.Message.NAN_PRODUCED); + } + return RDataFactory.createIntVector(result, complete); + } + + private static RAbstractDoubleVector evaluate2Double(Node node, RandFunction2_Double function, int length, RAbstractDoubleVector a, RAbstractDoubleVector b, RandGenerationProfiles profiles) { + int aLength = a.getLength(); + int bLength = b.getLength(); + if (aLength == 0 || bLength == 0) { + profiles.nanResult.enter(); + RError.warning(SHOW_CALLER, RError.Message.NAN_PRODUCED); + return createVectorOf(length, RRuntime.DOUBLE_NA); + } + + RNode.reportWork(node, length); + boolean complete = true; + boolean nans = false; + profiles.aCheck.enable(a); + profiles.bCheck.enable(b); + double[] result = new double[length]; + RRNG.getRNGState(); + for (int i = 0; i < length; i++) { + double aValue = a.getDataAt(i % aLength); + double bValue = b.getDataAt(i % bLength); + double value; + if (Double.isNaN(aValue) || Double.isNaN(bValue)) { + profiles.nan.enter(); + value = RRuntime.INT_NA; + if (profiles.aCheck.check(aValue) || profiles.bCheck.check(bValue)) { + complete = false; + } + } else { + if (!function.isValid(aValue, bValue)) { + profiles.errResult.enter(); + RError.warning(SHOW_CALLER, RError.Message.NA_PRODUCED); + return createVectorOf(length, Double.NaN); + } + value = function.evaluate(aValue, bValue); + if (Double.isNaN(value)) { + profiles.nan.enter(); + nans = true; + } + } + result[i] = value; + } + RRNG.putRNGState(); + if (nans) { + RError.warning(SHOW_CALLER, RError.Message.NAN_PRODUCED); + } + return RDataFactory.createDoubleVector(result, complete); + } + + private static RAbstractDoubleVector createVectorOf(int length, double element) { + double[] nansResult = new double[length]; + Arrays.fill(nansResult, element); + return RDataFactory.createDoubleVector(nansResult, false); + } + + /** + * Converts given value to actual length that should be used as length of the output vector. The + * argument must be cast using {@link #addLengthCast(CastBuilder)}. Using this node allows us to + * avoid casting of long vectors to integers, if we only need to know their length. + */ + protected abstract static class ConvertToLength extends Node { + public abstract int execute(RAbstractVector value); + + @Specialization(guards = "vector.getLength() == 1") + public int lengthOne(RAbstractVector vector, + @Cached("createNonPreserving()") CastIntegerNode castNode, + @Cached("create()") BranchProfile seenNA) { + int result = ((RAbstractIntVector) castNode.execute(vector)).getDataAt(0); + if (RRuntime.isNA(result)) { + seenNA.enter(); + throw RError.error(SHOW_CALLER, INVALID_UNNAMED_ARGUMENTS); + } + return result; + } + + @Specialization(guards = "vector.getLength() != 1") + public int notSingle(RAbstractVector vector) { + return vector.getLength(); + } + + private static void addLengthCast(CastBuilder casts) { + casts.arg(0).defaultError(SHOW_CALLER, INVALID_UNNAMED_ARGUMENTS).mustBe(abstractVectorValue()).asVector(); + } + } + + public abstract static class Function3_IntNode extends RExternalBuiltinNode.Arg4 { + private final RandFunction3_Int function; + @Child private ConvertToLength convertToLength = ConvertToLengthNodeGen.create(); + + protected Function3_IntNode(RandFunction3_Int function) { + this.function = function; + } + + @Override + protected void createCasts(CastBuilder casts) { + ConvertToLength.addLengthCast(casts); + casts.arg(1).asDoubleVector(); + casts.arg(2).asDoubleVector(); + casts.arg(3).asDoubleVector(); + } + + @Specialization + protected RAbstractIntVector evaluate(RAbstractVector length, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, + @Cached("create()") RandGenerationProfiles profiles) { + return evaluate3Int(this, function, convertToLength.execute(length), a, b, c, profiles); + } + } + + public abstract static class Function2_IntNode extends RExternalBuiltinNode.Arg3 { + private final RandFunction2_Int function; + @Child private ConvertToLength convertToLength = ConvertToLengthNodeGen.create(); + + protected Function2_IntNode(RandFunction2_Int function) { + this.function = function; + } + + @Override + protected void createCasts(CastBuilder casts) { + ConvertToLength.addLengthCast(casts); + casts.arg(1).asDoubleVector(); + casts.arg(2).asDoubleVector(); + } + + @Specialization + protected RAbstractIntVector evaluate(RAbstractVector length, RAbstractDoubleVector a, RAbstractDoubleVector b, + @Cached("create()") RandGenerationProfiles profiles) { + return evaluate3Int(this, function, convertToLength.execute(length), a, b, DUMMY_VECTOR, profiles); + } + } + + public abstract static class Function2_DoubleNode extends RExternalBuiltinNode.Arg3 { + private final RandFunction2_Double function; + @Child private ConvertToLength convertToLength = ConvertToLengthNodeGen.create(); + + protected Function2_DoubleNode(RandFunction2_Double function) { + this.function = function; + } + + @Override + protected void createCasts(CastBuilder casts) { + ConvertToLength.addLengthCast(casts); + casts.arg(1).asDoubleVector(); + casts.arg(2).asDoubleVector(); + } + + @Specialization + protected RAbstractDoubleVector evaluate(RAbstractVector length, RAbstractDoubleVector a, RAbstractDoubleVector b, + @Cached("create()") RandGenerationProfiles profiles) { + return evaluate2Double(this, function, convertToLength.execute(length), a, b, profiles); + } + } +} 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 74cf21b87fcb1104e4b3d67104eec9f6400a142c..e814c90a222325d9ba8f6e91524cbbdd602b2f08 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 @@ -13,62 +13,50 @@ package com.oracle.truffle.r.library.stats; 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.RExternalBuiltinNode; -import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RError.Message; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.nodes.RNode; -import com.oracle.truffle.r.runtime.ops.na.NAProfile; +import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Int; +import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.rng.RRNG; // transcribed from rbinom.c -public abstract class Rbinom extends RExternalBuiltinNode.Arg3 { +public final class Rbinom implements RandFunction2_Int { + + private final Qbinom qbinom = new Qbinom(); @TruffleBoundary private static double unifRand() { return RRNG.unifRand(); } - private final Qbinom qbinom = new Qbinom(); - - double rbinom(double nin, double pp, BranchProfile nanProfile) { + @Override + public int evaluate(double nin, double pp) { double psave = -1.0; int nsave = -1; if (!Double.isFinite(nin)) { - nanProfile.enter(); - return Double.NaN; + return RRuntime.INT_NA; } double r = MathConstants.forceint(nin); if (r != nin) { - nanProfile.enter(); - return Double.NaN; + return RRuntime.INT_NA; } /* n=0, p=0, p=1 are not errors <TSL> */ if (!Double.isFinite(pp) || r < 0 || pp < 0. || pp > 1.) { - nanProfile.enter(); - return Double.NaN; + return RRuntime.INT_NA; } if (r == 0 || pp == 0.) { return 0; } if (pp == 1.) { - return r; + return (int) r; } if (r >= Integer.MAX_VALUE) { /* * evade integer overflow, and r == INT_MAX gave only even values */ - return qbinom.evaluate(unifRand(), r, pp, /* lower_tail */false, /* log_p */false); + return (int) qbinom.evaluate(unifRand(), r, pp, /* lower_tail */false, /* log_p */false); } /* else */ int n = (int) r; @@ -258,47 +246,4 @@ public abstract class Rbinom extends RExternalBuiltinNode.Arg3 { } return ix; } - - @Override - protected void createCasts(CastBuilder casts) { - casts.arg(0).asDoubleVector(); - casts.arg(1).asDoubleVector(); - casts.arg(2).asDoubleVector(); - } - - @Specialization - protected Object rbinom(RAbstractDoubleVector n, RAbstractDoubleVector size, RAbstractDoubleVector prob, // - @Cached("create()") NAProfile na, // - @Cached("create()") BranchProfile nanProfile, // - @Cached("create()") VectorLengthProfile sizeProfile, // - @Cached("create()") VectorLengthProfile probProfile) { - int length = n.getLength(); - RNode.reportWork(this, length); - if (length == 1) { - double l = n.getDataAt(0); - if (Double.isNaN(l) || l < 0 || l > Integer.MAX_VALUE) { - throw RError.error(RError.SHOW_CALLER, Message.INVALID_UNNAMED_ARGUMENTS); - } - length = (int) l; - } - int sizeLength = sizeProfile.profile(size.getLength()); - int probLength = probProfile.profile(prob.getLength()); - - double[] result = new double[length]; - boolean complete = true; - boolean nans = false; - for (int i = 0; i < length; i++) { - double value = rbinom(size.getDataAt(i % sizeLength), prob.getDataAt(i % probLength), nanProfile); - if (na.isNA(value)) { - complete = false; - } else if (Double.isNaN(value)) { - nans = true; - } - result[i] = value; - } - if (nans) { - RError.warning(RError.SHOW_CALLER, RError.Message.NAN_PRODUCED); - } - return RDataFactory.createDoubleVector(result, complete); - } } 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 d6c1c25102fd42f084fee09109a1f3e796c46b28..641b1163688c4117d5b47a94d771ed72cdea9bea 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 @@ -11,60 +11,18 @@ */ package com.oracle.truffle.r.library.stats; -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.RExternalBuiltinNode; -import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -import com.oracle.truffle.r.runtime.nodes.RNode; -import com.oracle.truffle.r.runtime.rng.RandomNumberNode; +import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_DoubleAdapter; +import com.oracle.truffle.r.runtime.rng.RRNG; -/** - * TODO GnuR checks/updates {@code .Random.seed} across this call. TODO Honor min/max. - */ -public abstract class Rnorm extends RExternalBuiltinNode.Arg3 { - - @Child private RandomNumberNode random = new RandomNumberNode(); +public final class Rnorm extends RandFunction2_DoubleAdapter { private static final double BIG = 134217728; @Override - protected void createCasts(CastBuilder casts) { - casts.arg(1).asDoubleVector(); - casts.arg(2).asDoubleVector(); - } - - @Specialization - protected Object doRnorm(Object n, RAbstractDoubleVector mean, RAbstractDoubleVector stdDev, // - @Cached("create()") VectorLengthProfile meanProfile, // - @Cached("create()") VectorLengthProfile stdDevProfile) { - int nInt = 1; - if (n instanceof RAbstractVector) { - nInt = ((RAbstractVector) n).getLength(); - } - if (nInt == 1) { - nInt = castInt(castVector(n)); - } - RNode.reportWork(this, nInt); - - double[] numbers = random.executeDouble(nInt * 2); - double[] result = new double[numbers.length / 2]; - - int meanLength = meanProfile.profile(mean.getLength()); - int stdDEvLength = stdDevProfile.profile(stdDev.getLength()); - - /* unif_rand() alone is not of high enough precision */ - for (int i = 0; i < result.length; i++) { - double u1 = (int) (BIG * numbers[i * 2]) + numbers[i * 2 + 1]; - - double meanValue = mean.getDataAt(i % meanLength); - double stdDevValue = stdDev.getDataAt(i % stdDEvLength); - - result[i] = Random2.qnorm5(u1 / BIG, 0.0, 1.0, true, false) * stdDevValue + meanValue; - } - return RDataFactory.createDoubleVector(result, RDataFactory.COMPLETE_VECTOR); + public double evaluate(double mu, double sigma) { + // TODO: GnuR invokes norm_rand to get "rand" + double u1 = (int) (BIG * RRNG.unifRand()) + RRNG.unifRand(); + double rand = Random2.qnorm5(u1 / BIG, 0.0, 1.0, true, false); + return rand * sigma + mu; } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Runif.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Runif.java index 32416870e6c69823d02bd257b37bf4578a2916e2..443074c1da94cb62a6c9b028f9b258b32a6e3bbc 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Runif.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Runif.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,30 +22,18 @@ */ package com.oracle.truffle.r.library.stats; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.rng.RandomNumberNode; +import com.oracle.truffle.r.library.stats.RandGenerationFunctions.RandFunction2_Double; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.rng.RRNG; -/** - * TODO GnuR checks/updates {@code .Random.seed} across this call. - */ -public abstract class Runif extends RExternalBuiltinNode.Arg3 { - - @Child private RandomNumberNode random = new RandomNumberNode(); - - @Specialization - protected Object doRunif(Object n, Object min, Object max) { - // TODO full error checks - int nInt = castInt(castVector(n)); - double minDouble = castDouble(castVector(min)).getDataAt(0); - double maxDouble = castDouble(castVector(max)).getDataAt(0); - double delta = maxDouble - minDouble; +public final class Runif implements RandFunction2_Double { + @Override + public boolean isValid(double min, double max) { + return RRuntime.isFinite(min) && RRuntime.isFinite(max) && max >= min; + } - double[] result = random.executeDouble(nInt); - for (int i = 0; i < nInt; i++) { - result[i] = minDouble + result[i] * delta; - } - return RDataFactory.createDoubleVector(result, RDataFactory.COMPLETE_VECTOR); + @Override + public double evaluate(double min, double max) { + return min + RRNG.unifRand() * (max - min); } } 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 b9816f7fcd1a720f50ae63ce6cbc6a1bb4105150..ec49eda23c9b8ba99c2717648e5a5a3595d99f59 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 @@ -18,8 +18,12 @@ 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.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.LoopConditionProfile; +import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -49,31 +53,47 @@ public final class StatsFunctions { double evaluate(double a, double b, double c, boolean x); } + static final class StatFunctionProfiles { + final BranchProfile nan = BranchProfile.create(); + final NACheck aCheck = NACheck.create(); + final NACheck bCheck = NACheck.create(); + final NACheck cCheck = NACheck.create(); + final ConditionProfile copyAttrsFromA = ConditionProfile.createBinaryProfile(); + final ConditionProfile copyAttrsFromB = ConditionProfile.createBinaryProfile(); + final ConditionProfile copyAttrsFromC = ConditionProfile.createBinaryProfile(); + final VectorLengthProfile resultVectorLengthProfile = VectorLengthProfile.create(); + final LoopConditionProfile loopConditionProfile = LoopConditionProfile.createCountingProfile(); + + public static StatFunctionProfiles create() { + return new StatFunctionProfiles(); + } + } + private static RAbstractDoubleVector evaluate3(Node node, Function3_2 function, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, boolean x, boolean y, - BranchProfile nan, NACheck aCheck, NACheck bCheck, NACheck cCheck) { + StatFunctionProfiles profiles, UnaryCopyAttributesNode copyAttributesNode) { int aLength = a.getLength(); int bLength = b.getLength(); int cLength = c.getLength(); if (aLength == 0 || bLength == 0 || cLength == 0) { return RDataFactory.createEmptyDoubleVector(); } - int length = Math.max(aLength, Math.max(bLength, cLength)); + int length = profiles.resultVectorLengthProfile.profile(Math.max(aLength, Math.max(bLength, cLength))); RNode.reportWork(node, length); double[] result = new double[length]; boolean complete = true; boolean nans = false; - aCheck.enable(a); - bCheck.enable(b); - cCheck.enable(c); - for (int i = 0; i < length; i++) { + profiles.aCheck.enable(a); + profiles.bCheck.enable(b); + profiles.cCheck.enable(c); + for (int i = 0; profiles.loopConditionProfile.inject(i < length); i++) { double aValue = a.getDataAt(i % aLength); double bValue = b.getDataAt(i % bLength); double cValue = c.getDataAt(i % cLength); double value; if (Double.isNaN(aValue) || Double.isNaN(bValue) || Double.isNaN(cValue)) { - nan.enter(); - if (aCheck.check(aValue) || bCheck.check(bValue) || cCheck.check(cValue)) { + profiles.nan.enter(); + if (profiles.aCheck.check(aValue) || profiles.bCheck.check(bValue) || profiles.cCheck.check(cValue)) { value = RRuntime.DOUBLE_NA; complete = false; } else { @@ -82,7 +102,7 @@ public final class StatsFunctions { } else { value = function.evaluate(aValue, bValue, cValue, x, y); if (Double.isNaN(value)) { - nan.enter(); + profiles.nan.enter(); nans = true; } } @@ -91,7 +111,18 @@ public final class StatsFunctions { if (nans) { RError.warning(RError.SHOW_CALLER, RError.Message.NAN_PRODUCED); } - return RDataFactory.createDoubleVector(result, complete); + RDoubleVector resultVec = RDataFactory.createDoubleVector(result, complete); + + // copy attributes if necessary: + if (profiles.copyAttrsFromA.profile(aLength == length)) { + copyAttributesNode.execute(resultVec, a); + } else if (profiles.copyAttrsFromB.profile(bLength == length)) { + copyAttributesNode.execute(resultVec, b); + } else if (profiles.copyAttrsFromC.profile(cLength == length)) { + copyAttributesNode.execute(resultVec, c); + } + + return resultVec; } public abstract static class Function3_2Node extends RExternalBuiltinNode.Arg5 { @@ -111,12 +142,10 @@ public final class StatsFunctions { } @Specialization - protected RAbstractDoubleVector evaluate(RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, boolean x, boolean y, // - @Cached("create()") BranchProfile nan, // - @Cached("create()") NACheck aCheck, // - @Cached("create()") NACheck bCheck, // - @Cached("create()") NACheck cCheck) { - return evaluate3(this, function, a, b, c, x, y, nan, aCheck, bCheck, cCheck); + protected RAbstractDoubleVector evaluate(RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, boolean x, boolean y, + @Cached("create()") StatFunctionProfiles profiles, + @Cached("create()") UnaryCopyAttributesNode copyAttributesNode) { + return evaluate3(this, function, a, b, c, x, y, profiles, copyAttributesNode); } } @@ -136,12 +165,10 @@ public final class StatsFunctions { } @Specialization - protected RAbstractDoubleVector evaluate(RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, boolean x, // - @Cached("create()") BranchProfile nan, // - @Cached("create()") NACheck aCheck, // - @Cached("create()") NACheck bCheck, // - @Cached("create()") NACheck cCheck) { - return evaluate3(this, function, a, b, c, x, false /* dummy */, nan, aCheck, bCheck, cCheck); + protected RAbstractDoubleVector evaluate(RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, boolean x, + @Cached("create()") StatFunctionProfiles profiles, + @Cached("create()") UnaryCopyAttributesNode copyAttributesNode) { + return evaluate3(this, function, a, b, c, x, false /* dummy */, profiles, copyAttributesNode); } } 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 bc9a8097e0afd1b4b9d4f1119f307885cf0144fa..521ae38163e3b41b7ff25073eaaa2d9fcae7dbd8 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 @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; import com.oracle.truffle.api.frame.MaterializedFrame; @@ -100,13 +101,19 @@ public abstract class RBuiltinPackage { return name; } + private static final ConcurrentHashMap<String, String[]> rFilesCache = new ConcurrentHashMap<>(); + /** * Get a list of R override files for package {@code pkgName}, from the {@code pkgName/R} * subdirectory. */ public static ArrayList<Source> getRFiles(String pkgName) { ArrayList<Source> componentList = new ArrayList<>(); - String[] rFileContents = ResourceHandlerFactory.getHandler().getRFiles(RBuiltinPackage.class, pkgName); + String[] rFileContents = rFilesCache.get(pkgName); + if (rFileContents == null) { + rFileContents = ResourceHandlerFactory.getHandler().getRFiles(RBuiltinPackage.class, pkgName); + rFilesCache.put(pkgName, rFileContents); + } for (String rFileContent : rFileContents) { Source content = RSource.fromTextInternal(rFileContent, RSource.Internal.R_IMPL); componentList.add(content); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java index f5b340906fdc58d2532f2d91fe1a76a93178d8f8..0550a55c3bdd9628b69680a20f5fda5193ade6b6 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java @@ -161,7 +161,7 @@ public final class RBuiltinPackages implements RBuiltinLookup { return function; } RootCallTarget callTarget = RBuiltinNode.createArgumentsCallTarget(builtinFactory); - function = RDataFactory.createFunction(builtinFactory.getName(), callTarget, builtinFactory, null); + function = RDataFactory.createFunction(builtinFactory.getName(), "base", callTarget, builtinFactory, null); cachedBuiltinFunctions.put(methodName, function); return function; } catch (Throwable t) { 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 3e2232794d820121f706f64d602e1573d07f115a..c239b07b293abaec17216c177dff74b1cb2e986b 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 @@ -38,7 +38,6 @@ import com.oracle.truffle.r.nodes.builtin.base.GetFunctionsFactory.GetNodeGen; import com.oracle.truffle.r.nodes.function.FormalArguments; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; import com.oracle.truffle.r.nodes.function.SaveArgumentsNode; -import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -85,8 +84,7 @@ public abstract class Args extends RBuiltinNode { String newDesc = "args(" + rootNode.getDescription() + ")"; FunctionDefinitionNode newNode = FunctionDefinitionNode.create(RSyntaxNode.LAZY_DEPARSE, rootNode.getFrameDescriptor(), null, SaveArgumentsNode.NO_ARGS, ConstantNode.create(RSyntaxNode.LAZY_DEPARSE, RNull.instance), formals, newDesc, null); - RDeparse.ensureSourceSection(newNode); - return RDataFactory.createFunction(newDesc, Truffle.getRuntime().createCallTarget(newNode), null, REnvironment.globalEnv().getFrame()); + return RDataFactory.createFunction(newDesc, RFunction.NO_NAME, Truffle.getRuntime().createCallTarget(newNode), null, REnvironment.globalEnv().getFrame()); } @Specialization(guards = {"!isRFunction(fun)", "!isRAbstractStringVector(fun)"}) 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 20b61c1e9c4bc222f8520b032360d290b780279b..48e9c12212719efece862ee4d5346b8011cae3fe 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 @@ -76,7 +76,7 @@ public abstract class AsCharacter extends RBuiltinNode { } else if (elem instanceof RStringVector && ((RStringVector) elem).getLength() == 1) { data[i] = ((RStringVector) elem).getDataAt(0); } else { - data[i] = RDeparse.deparse(elem, RDeparse.MAX_Cutoff, true, 0, -1); + data[i] = RDeparse.deparse(elem); } if (RRuntime.isNA(data[i])) { complete = RDataFactory.INCOMPLETE_VECTOR; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java index 4c326d7e1158209e3a6a9129e329a6e0ec26d5f7..4c7ca302a832f3e56e0e2f08733f2e77564cdcd6 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,7 +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.nodes.builtin.CastBuilder.Predef.instanceOf; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -41,7 +41,6 @@ import com.oracle.truffle.r.nodes.function.FormalArguments; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; import com.oracle.truffle.r.nodes.function.SaveArgumentsNode; 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.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; @@ -148,8 +147,7 @@ public abstract class AsFunction extends RBuiltinNode { FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<as.function.default>", descriptor); FrameSlotChangeMonitor.initializeEnclosingFrame(descriptor, envir.getFrame()); FunctionDefinitionNode rootNode = FunctionDefinitionNode.create(RSyntaxNode.LAZY_DEPARSE, descriptor, null, saveArguments, (RSyntaxNode) body, formals, "from AsFunction", null); - RDeparse.ensureSourceSection(rootNode); RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); - return RDataFactory.createFunction(RFunction.NO_NAME, callTarget, null, envir.getFrame()); + return RDataFactory.createFunction(RFunction.NO_NAME, RFunction.NO_NAME, callTarget, null, envir.getFrame()); } } 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 8292df94d1c110f189f06eca36a89be4d8cabc85..1ce4dba99c396ca5e9a4bb6923dca210d8f7c020 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 @@ -96,6 +96,8 @@ import com.oracle.truffle.r.nodes.builtin.fastr.FastRInspect; import com.oracle.truffle.r.nodes.builtin.fastr.FastRInspectNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRInterop; import com.oracle.truffle.r.nodes.builtin.fastr.FastRInteropFactory; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRPkgSource; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRPkgSourceNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRRefCountInfo; import com.oracle.truffle.r.nodes.builtin.fastr.FastRRefCountInfoNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRStackTrace; @@ -351,6 +353,7 @@ public class BasePackage extends RBuiltinPackage { add(FastRInterop.IsExecutable.class, FastRInteropFactory.IsExecutableNodeGen::create); add(FastRInterop.ToBoolean.class, FastRInteropFactory.ToBooleanNodeGen::create); add(FastRRefCountInfo.class, FastRRefCountInfoNodeGen::create); + add(FastRPkgSource.class, FastRPkgSourceNodeGen::create); add(FastRStackTrace.class, FastRStackTraceNodeGen::create); add(FastRProfAttr.class, FastRStatsFactory.FastRProfAttrNodeGen::create); add(FastRProfTypecounts.class, FastRStatsFactory.FastRProfTypecountsNodeGen::create); 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 79500f3f23c8f6155eed7de5437f96f11c3ec7bf..df46b16704bc913cca3af30da9027533d27569f2 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 @@ -178,6 +178,10 @@ public abstract class ConnectionFunctions { private static void swap(CastBuilder casts) { casts.arg("swap").asLogicalVector().findFirst().notNA().map(toBoolean()); } + + private static void method(CastBuilder casts) { + casts.arg("method").asStringVector().findFirst(); + } } @RBuiltin(name = "file", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding", "method", "raw"}, behavior = IO) @@ -189,7 +193,7 @@ public abstract class ConnectionFunctions { Casts.open(casts); casts.arg("blocking").asLogicalVector().findFirst().mustBe(logicalTrue(), RError.Message.NYI, "non-blocking mode not supported").map(toBoolean()); Casts.encoding(casts); - casts.arg("method").asStringVector().findFirst(); + Casts.method(casts); Casts.raw(casts); } @@ -356,7 +360,7 @@ public abstract class ConnectionFunctions { } } - @RBuiltin(name = "url", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding"}, behavior = IO) + @RBuiltin(name = "url", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding", "method"}, behavior = IO) public abstract static class URLConnection extends RBuiltinNode { @Override @@ -365,11 +369,13 @@ public abstract class ConnectionFunctions { Casts.open(casts); Casts.blocking(casts); Casts.encoding(casts); + Casts.method(casts); } @Specialization @TruffleBoundary - protected RAbstractIntVector urlConnection(String url, String open, @SuppressWarnings("unused") boolean blocking, @SuppressWarnings("unused") String encoding) { + protected RAbstractIntVector urlConnection(String url, String open, @SuppressWarnings("unused") boolean blocking, @SuppressWarnings("unused") String encoding, + @SuppressWarnings("unused") String method) { try { return new URLRConnection(url, open).asVector(); } catch (MalformedURLException ex) { 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 c41d24f58409f369f09262b4a3bbf0d4fecbf216..e5ae35b08c784065f46fd10c6b38abd451044f51 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 @@ -392,7 +392,7 @@ public class EnvFunctions { RRootNode root = (RRootNode) fun.getTarget().getRootNode(); RootCallTarget target = root.duplicateWithNewFrameDescriptor(); FrameSlotChangeMonitor.initializeEnclosingFrame(target.getRootNode().getFrameDescriptor(), enclosingFrame); - return RDataFactory.createFunction(fun.getName(), target, null, enclosingFrame); + return RDataFactory.createFunction(fun.getName(), fun.getPackageName(), target, null, enclosingFrame); } @Specialization 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 69c479a93f36952fce3275cc57265b45a24cb5cc..8ac93354d9a2fdb4f9223c82978ee91a8110bf19 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 @@ -136,7 +136,7 @@ public abstract class Parse extends RBuiltinNode { } try { Source source = srcFile != RNull.instance ? createSource(srcFile, coalescedLines) : createSource(conn, coalescedLines); - RExpression exprs = RContext.getEngine().parse(null, source); + RExpression exprs = RContext.getEngine().parse(source); if (n > 0 && n < exprs.getLength()) { Object[] subListData = new Object[n]; for (int i = 0; i < n; i++) { 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 2c0fb7913408c8093467208121e0f5cd7609bc68..1f195c7f27e065bb0209b212e9441f03efa1711d 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 @@ -40,6 +40,8 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; import com.oracle.truffle.r.runtime.ops.UnaryArithmetic; import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory; @@ -78,6 +80,28 @@ public abstract class Round extends RBuiltinNode { return check.check(x) ? RRuntime.DOUBLE_NA : x; } + @Specialization + protected RDoubleVector round(RAbstractLogicalVector x, @SuppressWarnings("unused") int digits) { + double[] data = new double[x.getLength()]; + check.enable(x); + for (int i = 0; i < data.length; i++) { + byte val = x.getDataAt(i); + data[i] = check.check(val) ? RRuntime.DOUBLE_NA : val; + } + return RDataFactory.createDoubleVector(data, check.neverSeenNA()); + } + + @Specialization + protected RDoubleVector round(RAbstractIntVector x, @SuppressWarnings("unused") int digits) { + double[] data = new double[x.getLength()]; + check.enable(x); + for (int i = 0; i < data.length; i++) { + int val = x.getDataAt(i); + data[i] = check.check(val) ? RRuntime.DOUBLE_NA : val; + } + return RDataFactory.createDoubleVector(data, check.neverSeenNA()); + } + @Specialization(guards = "digits == 0") protected double round(double x, @SuppressWarnings("unused") int digits) { check.enable(x); 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 14adfe090df8ff15546d3b3680d86abfba13f872..7486acd13667c940d913dad3a0d28e0a6a916a1f 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 @@ -48,15 +48,16 @@ import com.oracle.truffle.r.library.stats.CovcorNodeGen; import com.oracle.truffle.r.library.stats.CutreeNodeGen; import com.oracle.truffle.r.library.stats.Dbinom; import com.oracle.truffle.r.library.stats.DoubleCentreNodeGen; -import com.oracle.truffle.r.library.stats.GammaFunctionsFactory.QgammaNodeGen; +import com.oracle.truffle.r.library.stats.GammaFunctions.QgammaFunc; 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; -import com.oracle.truffle.r.library.stats.RbinomNodeGen; -import com.oracle.truffle.r.library.stats.RnormNodeGen; -import com.oracle.truffle.r.library.stats.RunifNodeGen; +import com.oracle.truffle.r.library.stats.RandGenerationFunctionsFactory; +import com.oracle.truffle.r.library.stats.Rbinom; +import com.oracle.truffle.r.library.stats.Rnorm; +import com.oracle.truffle.r.library.stats.Runif; import com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineCoefNodeGen; import com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineEvalNodeGen; import com.oracle.truffle.r.library.stats.StatsFunctionsFactory; @@ -361,17 +362,17 @@ public class ForeignFunctions { case "qnorm": return StatsFunctionsFactory.Function3_2NodeGen.create(new Qnorm()); case "rnorm": - return RnormNodeGen.create(); + return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new Rnorm()); case "runif": - return RunifNodeGen.create(); + return RandGenerationFunctionsFactory.Function2_DoubleNodeGen.create(new Runif()); case "qgamma": - return QgammaNodeGen.create(); + return StatsFunctionsFactory.Function3_2NodeGen.create(new QgammaFunc()); case "dbinom": return StatsFunctionsFactory.Function3_1NodeGen.create(new Dbinom()); case "qbinom": return StatsFunctionsFactory.Function3_2NodeGen.create(new Qbinom()); case "rbinom": - return RbinomNodeGen.create(); + return RandGenerationFunctionsFactory.Function2_IntNodeGen.create(new Rbinom()); case "pbinom": return StatsFunctionsFactory.Function3_2NodeGen.create(new Pbinom()); case "pf": 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 15be08089ae5981033eebd892c300a56eb68abe4..d8de3b9f0c34652365a9f3a7665984c8d9426eb6 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 @@ -26,6 +26,7 @@ import java.io.IOException; import java.io.PrintWriter; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.nodes.RRootNode; import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.function.FormalArguments; @@ -36,6 +37,8 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; final class FunctionPrinter extends AbstractValuePrinter<RFunction> { @@ -75,9 +78,14 @@ final class FunctionPrinter extends AbstractValuePrinter<RFunction> { out.print(rBuiltin.getName()); out.print("\")"); } else { - final boolean useSource = printCtx.parameters().getUseSource(); - String source = ((RRootNode) operand.getTarget().getRootNode()).getSourceCode(); - if (source == null || !useSource) { + String source = null; + if (printCtx.parameters().getUseSource()) { + SourceSection sourceSection = ((RSyntaxFunction) operand.getRootNode()).getLazySourceSection(); + if (sourceSection != null && sourceSection != RSyntaxNode.LAZY_DEPARSE) { + source = sourceSection.getCode(); + } + } + if (source == null) { source = RDeparse.deparse(operand); } REnvironment env = RArguments.getEnvironment(operand.getEnclosingFrame()); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/S4ObjectPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/S4ObjectPrinter.java index b97c2ce73a9f1d9c34be5e0bd899e93f4edfde28..2807fa516e19ee783ca295440462030b83e552b4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/S4ObjectPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/S4ObjectPrinter.java @@ -44,8 +44,10 @@ final class S4ObjectPrinter implements ValuePrinter<RS4Object> { public void print(RS4Object object, PrintContext printCtx) throws IOException { final PrintWriter out = printCtx.output(); out.print("<S4 Type Object>"); - for (RAttribute attr : object.getAttributes()) { - printAttribute(attr, printCtx); + if (object.getAttributes() != null) { + for (RAttribute attr : object.getAttributes()) { + printAttribute(attr, printCtx); + } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java index 2f0e0a4bcaf03a628376bffb3468fb5ea6e78533..b77b3019496e26cce897c654b54539a5a57449ef 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java @@ -22,35 +22,164 @@ */ package com.oracle.truffle.r.nodes.builtin.fastr; +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.FileWriter; +import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; + +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; + +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.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.FunctionDefinitionNode; +import com.oracle.truffle.r.nodes.function.PromiseHelperNode; +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.RRuntime; +import com.oracle.truffle.r.runtime.RSerialize; +import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.conn.StdConnections; +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.RPromise; +import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.instrument.RPackageSource; +import com.oracle.truffle.r.runtime.env.REnvironment; -public class FastRPkgSource { +/** + * Outputs the deparsed source for functions in one or more loaded packages to the + * {@code Rpkgsource} directory., for use by e.g., a source-level debugger. + */ +@RBuiltin(name = ".fastr.pkgsource", kind = PRIMITIVE, visibility = OFF, parameterNames = {"pkgs", "verbose"}, behavior = COMPLEX) +public abstract class FastRPkgSource extends RBuiltinNode { + public static final String PKGSOURCE_PROJECT = "Rpkgsource"; + private static final String SLASH_SWAP = "_slash_"; + + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{RNull.instance, RRuntime.LOGICAL_FALSE}; + } + + @Override + public void createCasts(CastBuilder casts) { + casts.arg("pkgs").mustBe(stringValue()); + casts.arg("verbose").asLogicalVector().findFirst().notNA().map(toBoolean()); + } + + @Specialization + public RNull pkgSource(VirtualFrame frame, @SuppressWarnings("unused") RNull pkgs, boolean verbose) { + String[] searchPath = REnvironment.searchPath(); + for (String s : searchPath) { + REnvironment env = REnvironment.lookupOnSearchPath(s); + String pkg = env.isPackageEnv(); + if (pkg != null) { + pkgSource(frame, RDataFactory.createStringVectorFromScalar(pkg.replace("package:", "")), verbose); + } + } + return RNull.instance; + } - public abstract static class PreLoad extends RExternalBuiltinNode.Arg2 { - @Specialization - protected RNull preLoad(RAbstractStringVector pkg, RAbstractStringVector fname) { - RPackageSource.preLoad(pkg.getDataAt(0), fname.getDataAt(0)); - return RNull.instance; + @Specialization + public RNull pkgSource(VirtualFrame frame, RAbstractStringVector pkgs, boolean verbose) { + for (int i = 0; i < pkgs.getLength(); i++) { + String pkg = pkgs.getDataAt(i); + REnvironment env = REnvironment.getRegisteredNamespace(pkg); + if (env == null) { + notFound(pkg); + } else { + if (verbose) { + output("processing package: ", false); + output(pkg, true); + } + RStringVector names = env.ls(true, null, false); + for (int n = 0; n < names.getLength(); n++) { + String name = names.getDataAt(n); + Object value = env.get(name); + try { + if (value instanceof RPromise) { + value = PromiseHelperNode.evaluateSlowPath(frame, (RPromise) value); + } + if (value instanceof RFunction) { + RFunction fun = (RFunction) value; + if (!fun.isBuiltin()) { + if (verbose) { + output("processing function ", false); + output(name, true); + } + String deparseResult = RDeparse.deparseSyntaxElement((FunctionDefinitionNode) fun.getRootNode()); + saveSource(pkg, name, deparseResult); + } + } + } catch (Throwable t) { + noDeparse(pkg, name); + } + } + } } + return RNull.instance; } - public abstract static class PostLoad extends RExternalBuiltinNode.Arg3 { - @Specialization - protected RNull postLoad(RAbstractStringVector pkg, RAbstractStringVector fname, Object val) { - RPackageSource.postLoad(pkg.getDataAt(0), fname.getDataAt(0), val); - return RNull.instance; + @TruffleBoundary + private void output(String msg, boolean nl) { + try { + StdConnections.getStdout().writeString(msg, nl); + } catch (IOException ex) { + throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); } } - public abstract static class Done extends RExternalBuiltinNode.Arg1 { - @Specialization - protected RNull done(@SuppressWarnings("unused") RAbstractStringVector pkg) { - RPackageSource.saveMap(); - return RNull.instance; + @TruffleBoundary + private void notFound(String pkg) { + RError.warning(this, RError.Message.GENERIC, String.format("namespace '%s' not found - ignoring", pkg)); + } + + @TruffleBoundary + private void noDeparse(String pkg, String fname) { + RError.warning(this, RError.Message.GENERIC, String.format("function '%s::%s' failed to deparse - ignoring", pkg, fname)); + } + + private static void saveSource(String pkg, String fname, String deparseResult) { + RSerialize.setSaveDeparse(false); + try { + Path target = targetPath(pkg, fname); + try (FileWriter wr = new FileWriter(target.toFile())) { + wr.write(deparseResult); + } + } catch (IOException ex) { + throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, ex.getMessage()); } } + + /** + * Some function names do not map into useful or even legal filenames. This method takes care of + * that. + */ + private static String mungeName(String fname) { + String result = fname; + result = result.replace("/", SLASH_SWAP); + return result; + } + + private static Path targetPath(String pkg, String fnameArg) throws IOException { + Path targetDir = dirPath().resolve(pkg); + Files.createDirectories(targetDir); + String fname = mungeName(fnameArg); + Path target = targetDir.resolve(fname + ".R"); + return target; + } + + private static Path dirPath() { + return FileSystems.getDefault().getPath(REnvVars.rHome(), PKGSOURCE_PROJECT); + } + } diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b72e022b321a7d8fa76f41a506f474f6bd84ab90 --- /dev/null +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java @@ -0,0 +1,239 @@ +/* + * 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.test; + +import org.junit.Assert; +import org.junit.Test; + +import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.r.engine.TruffleRLanguage; +import com.oracle.truffle.r.nodes.access.WriteVariableSyntaxNode; +import com.oracle.truffle.r.nodes.control.BlockNode; +import com.oracle.truffle.r.nodes.control.ReplacementDispatchNode; +import com.oracle.truffle.r.nodes.function.RCallNode; +import com.oracle.truffle.r.nodes.function.RCallSpecialNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.FastROptions; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RootWithBody; +import com.oracle.truffle.r.runtime.data.RExpression; +import com.oracle.truffle.r.runtime.data.RLanguage; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; +import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; +import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction; +import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; +import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor; + +public class SpecialCallTest extends TestBase { + private static final class CountCallsVisitor extends RSyntaxVisitor<Void> { + + public int normal; + public int special; + + CountCallsVisitor(RootCallTarget callTarget) { + accept(((RootWithBody) callTarget.getRootNode()).getBody().asRSyntaxNode()); + } + + @Override + protected Void visit(RSyntaxCall element) { + if (element instanceof RCallSpecialNode) { + special++; + } else if (element instanceof RCallNode) { + normal++; + } else { + assert element instanceof ReplacementDispatchNode || element instanceof WriteVariableSyntaxNode || element instanceof BlockNode : "unexpected node while testing"; + } + accept(element.getSyntaxLHS()); + for (RSyntaxElement arg : element.getSyntaxArguments()) { + accept(arg); + } + return null; + } + + @Override + protected Void visit(RSyntaxConstant element) { + return null; + } + + @Override + protected Void visit(RSyntaxLookup element) { + return null; + } + + @Override + protected Void visit(RSyntaxFunction element) { + for (RSyntaxElement arg : element.getSyntaxArgumentDefaults()) { + accept(arg); + } + accept(element.getSyntaxBody()); + return null; + } + } + + private static final class PrintCallsVisitor extends RSyntaxVisitor<Void> { + + private String indent = ""; + + void print(RootCallTarget callTarget) { + System.out.println(); + accept(((RootWithBody) callTarget.getRootNode()).getBody().asRSyntaxNode()); + } + + @Override + protected Void visit(RSyntaxCall element) { + System.out.println(indent + "call " + element.getClass().getSimpleName()); + indent += " "; + System.out.println(indent.substring(2) + "lhs:"); + accept(element.getSyntaxLHS()); + printArgs(element.getSyntaxSignature(), element.getSyntaxArguments()); + indent = indent.substring(4); + return null; + } + + @Override + protected Void visit(RSyntaxConstant element) { + System.out.println(indent + "constant " + element.getClass().getSimpleName() + " " + element.getValue().getClass().getSimpleName() + " " + element.getValue()); + return null; + } + + @Override + protected Void visit(RSyntaxLookup element) { + System.out.println(indent + "lookup " + element.getClass().getSimpleName() + " " + element.getIdentifier()); + return null; + } + + @Override + protected Void visit(RSyntaxFunction element) { + System.out.println(indent + "function " + element.getClass().getSimpleName()); + indent += " "; + printArgs(element.getSyntaxSignature(), element.getSyntaxArgumentDefaults()); + indent = indent.substring(4); + for (RSyntaxElement arg : element.getSyntaxArgumentDefaults()) { + accept(arg); + } + System.out.println(indent.substring(2) + "body:"); + accept(element.getSyntaxBody()); + return null; + } + + private void printArgs(ArgumentsSignature signature, RSyntaxElement[] arguments) { + for (int i = 0; i < arguments.length; i++) { + System.out.println(indent.substring(2) + "arg " + (signature.getName(i) == null ? "<unnamed>" : signature.getName(i))); + accept(arguments[i]); + } + } + } + + @Test + public void testBasic() { + // check a case with no calls + assertCallCounts("library(stats)", 0, 1, 0, 1); + } + + @Test + public void testArithmetic() { + assertCallCounts("1 + 1", 1, 0, 1, 0); + assertCallCounts("1 + 1 * 2 + 4", 3, 0, 3, 0); + + assertCallCounts("{ a <- 1; b <- 2; a + b }", 1, 0, 1, 0); + assertCallCounts("{ a <- 1; b <- 2; c <- 3; a + b * 2 * c}", 3, 0, 3, 0); + + assertCallCounts("{ a <- data.frame(a=1); b <- 2; c <- 3; a + b * 2 * c}", 3, 1, 2, 2); + assertCallCounts("{ a <- 1; b <- data.frame(a=1); c <- 3; a + b * 2 * c}", 3, 1, 0, 4); + + assertCallCounts("1 %*% 1", 0, 1, 0, 1); + } + + @Test + public void testSubset() { + assertCallCounts("{ a <- 1:10; a[1] }", 1, 1, 1, 1); + assertCallCounts("{ a <- c(1,2,3,4); a[2] }", 1, 1, 1, 1); + assertCallCounts("{ a <- c(1,2,3,4); a[4] }", 1, 1, 1, 1); + assertCallCounts("{ a <- list(c(1,2,3,4),2,3); a[1] }", 1, 2, 1, 2); + + assertCallCounts("{ a <- c(1,2,3,4); a[0.1] }", 1, 1, 0, 2); + assertCallCounts("{ a <- c(1,2,3,4); a[5] }", 1, 1, 0, 2); + assertCallCounts("{ a <- c(1,2,3,4); a[0] }", 1, 1, 0, 2); + assertCallCounts("{ a <- c(1,2,3,4); a[-1] }", 0, 3, 0, 3); // "-1" is a unary expression + assertCallCounts("{ a <- c(1,2,3,4); b <- -1; a[b] }", 1, 2, 0, 3); + assertCallCounts("{ a <- c(1,2,3,4); a[NA_integer_] }", 1, 1, 0, 2); + } + + @Test + public void testSubscript() { + assertCallCounts("{ a <- 1:10; a[[1]] }", 1, 1, 1, 1); + assertCallCounts("{ a <- c(1,2,3,4); a[[2]] }", 1, 1, 1, 1); + assertCallCounts("{ a <- c(1,2,3,4); a[[4]] }", 1, 1, 1, 1); + assertCallCounts("{ a <- list(c(1,2,3,4),2,3); a[[1]] }", 1, 2, 1, 2); + assertCallCounts("{ a <- list(a=c(1,2,3,4),2,3); a[[1]] }", 1, 2, 1, 2); + assertCallCounts("{ a <- c(1,2,3,4); a[[0.1]] }", 1, 1, 1, 1); + + assertCallCounts("{ a <- c(1,2,3,4); a[[5]] }", 1, 1, 0, 2); + assertCallCounts("{ a <- c(1,2,3,4); a[[0]] }", 1, 1, 0, 2); + assertCallCounts("{ a <- c(1,2,3,4); b <- -1; a[[b]] }", 1, 2, 0, 3); + assertCallCounts("{ a <- c(1,2,3,4); a[[NA_integer_]] }", 1, 1, 0, 2); + } + + private static void assertCallCounts(String str, int initialSpecialCount, int initialNormalCount, int finalSpecialCount, int finalNormalCount) { + if (!FastROptions.UseSpecials.getBooleanValue()) { + return; + } + Source source = Source.newBuilder(str).mimeType(TruffleRLanguage.MIME).name("test").build(); + + RExpression expression = testVMContext.getThisEngine().parse(source); + assert expression.getLength() == 1; + RootCallTarget callTarget = testVMContext.getThisEngine().makePromiseCallTarget(((RLanguage) expression.getDataAt(0)).getRep().asRSyntaxNode().asRNode(), "test"); + + try { + CountCallsVisitor count1 = new CountCallsVisitor(callTarget); + Assert.assertEquals("initial special call count '" + str + "': ", initialSpecialCount, count1.special); + Assert.assertEquals("initial normal call count '" + str + "': ", initialNormalCount, count1.normal); + + try { + callTarget.call(REnvironment.globalEnv().getFrame()); + } catch (RError e) { + // ignore + } + + CountCallsVisitor count2 = new CountCallsVisitor(callTarget); + Assert.assertEquals("special call count after first call '" + str + "': ", finalSpecialCount, count2.special); + Assert.assertEquals("normal call count after first call '" + str + "': ", finalNormalCount, count2.normal); + + try { + callTarget.call(REnvironment.globalEnv().getFrame()); + } catch (RError e) { + // ignore + } + + CountCallsVisitor count3 = new CountCallsVisitor(callTarget); + Assert.assertEquals("special call count after second call '" + str + "': ", finalSpecialCount, count3.special); + Assert.assertEquals("normal call count after second call '" + str + "': ", finalNormalCount, count3.normal); + } catch (AssertionError e) { + new PrintCallsVisitor().print(callTarget); + throw e; + } + } +} 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 7a62c4fc65ad83af7ccc6bf359d644c292c4f581..4b35745a57d38575a5f0b42a2bcb630315bdc1bc 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 @@ -23,7 +23,6 @@ package com.oracle.truffle.r.nodes; import java.util.List; -import java.util.Map; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; @@ -56,6 +55,7 @@ import com.oracle.truffle.r.runtime.FastROptions; 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.RShareable; 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; @@ -67,23 +67,11 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; /** * This class can be used to build fragments of Truffle AST that correspond to R language * constructs: calls, lookups, constants and functions. - * - * Additionally, this class has helper functions to issue (parser) warnings and - * */ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { - private final Map<String, Object> constants; private CodeBuilderContext context = CodeBuilderContext.DEFAULT; - public RASTBuilder() { - this.constants = null; - } - - public RASTBuilder(Map<String, Object> constants) { - this.constants = constants; - } - @Override public RSyntaxNode call(SourceSection source, RSyntaxNode lhs, List<Argument<RSyntaxNode>> args) { if (lhs instanceof RSyntaxLookup) { @@ -105,6 +93,15 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { } } else if (args.size() == 2) { switch (symbol) { + case "$": + case "@": + if (args.get(1).value instanceof RSyntaxLookup) { + RSyntaxLookup lookup = (RSyntaxLookup) args.get(1).value; + // FastR differs from GNUR: we only use string constants to represent + // field and slot lookups, while GNUR uses symbols + args.set(1, RCodeBuilder.argument(args.get(1).source, args.get(1).name, constant(lookup.getLazySourceSection(), lookup.getIdentifier()))); + } + break; case "while": return new WhileNode(source, lhsLookup, args.get(0).value, args.get(1).value); case "if": @@ -255,6 +252,12 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { if (value instanceof String && !RRuntime.isNA((String) value)) { return ConstantNode.create(source, ((String) value).intern()); } else { + if (value instanceof RShareable) { + RShareable shareable = (RShareable) value; + if (!shareable.isSharedPermanent()) { + return ConstantNode.create(source, shareable.makeSharedPermanent()); + } + } return ConstantNode.create(source, value); } } @@ -274,12 +277,6 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { @Override public RSyntaxNode lookup(SourceSection source, String symbol, boolean functionLookup) { assert source != null; - if (constants != null && symbol.startsWith("C")) { - Object object = constants.get(symbol); - if (object != null) { - return ConstantNode.create(source, object); - } - } if (!functionLookup) { int index = getVariadicComponentIndex(symbol); if (index != -1) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java index d59fc7e3ff22afcb38af5fb37c567cdae6c0e8ef..eb785b3c7cc1cda98117c71df3e407934d3390c2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java @@ -22,7 +22,6 @@ */ package com.oracle.truffle.r.nodes; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.VirtualFrame; @@ -69,36 +68,37 @@ public abstract class RRootNode extends RootNode implements HasSignature { } } + @Override public abstract RootCallTarget duplicateWithNewFrameDescriptor(); - protected void verifyEnclosingAssumptions(VirtualFrame vf) { + protected final void verifyEnclosingAssumptions(VirtualFrame vf) { RArguments.setIsIrregular(vf, irregularFrameProfile.profile(RArguments.getIsIrregular(vf))); } /** * @return The number of parameters this functions expects */ - public int getParameterCount() { + public final int getParameterCount() { return formalArguments.getSignature().getLength(); } /** * @return {@link #formalArguments} */ - public FormalArguments getFormalArguments() { + public final FormalArguments getFormalArguments() { return formalArguments; } @Override - public ArgumentsSignature getSignature() { + public final ArgumentsSignature getSignature() { return formalArguments.getSignature(); } - public FastPathFactory getFastPath() { + public final FastPathFactory getFastPath() { return fastPath; } - public void setFastPath(FastPathFactory fastPath) { + public final void setFastPath(FastPathFactory fastPath) { this.fastPath = fastPath; } @@ -110,16 +110,6 @@ public abstract class RRootNode extends RootNode implements HasSignature { public abstract RBuiltinFactory getBuiltin(); - @TruffleBoundary - public String getSourceCode() { - SourceSection ss = getSourceSection(); - if (ss != null) { - return ss.getCode(); - } else { - return null; - } - } - @Override public boolean isCloningAllowed() { return true; 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 e6f9d802e696bc4f99360bc4ff7761d45f200c55..2099f1442ea7ac6c25ce9609fc63533f3d42770c 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 @@ -49,6 +49,10 @@ public abstract class UnaryCopyAttributesNode extends RBaseNode { this.copyAllAttributes = copyAllAttributes; } + public static UnaryCopyAttributesNode create() { + return UnaryCopyAttributesNodeGen.create(true); + } + public abstract RAbstractVector execute(RAbstractVector target, RAbstractVector left); protected boolean containsMetadata(RAbstractVector vector, RAttributeProfiles attrProfiles) { 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 559a17359f24bb6c206ec009e4ad06b87e768f66..ea86da6f090ada1bea4c02162a1939ddb0e4f6df 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 @@ -117,11 +117,6 @@ public final class RBuiltinRootNode extends RRootNode { throw RInternalError.shouldNotReachHere("set containsDispatch on builtin " + factory.getName()); } - @Override - public String getSourceCode() { - throw RInternalError.shouldNotReachHere(); - } - @Override public String getName() { return "RBuiltin(" + builtin + ")"; 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 1e0d45dfc2e5aa3d9ca3f66eb0c9cb9367680a62..936e2babd89f1a40e0485779285835a07c622653 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 @@ -38,7 +38,6 @@ import com.oracle.truffle.r.nodes.access.RemoveAndAnswerNode; import com.oracle.truffle.r.nodes.access.WriteVariableNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.function.RCallSpecialNode; -import com.oracle.truffle.r.nodes.function.RCallSpecialNode.RecursiveSpecialBailout; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.nodes.unary.GetNonSharedNodeGen; import com.oracle.truffle.r.runtime.ArgumentsSignature; @@ -241,10 +240,10 @@ abstract class ReplacementNode extends OperatorNode { RNode extractFunc = target; for (int i = calls.size() - 1; i >= 1; i--) { extractFunc = createSpecialFunctionQuery(calls.get(i), extractFunc.asRSyntaxNode(), codeBuilderContext); - ((RCallSpecialNode) extractFunc).setPropagateFullCallNeededException(true); + ((RCallSpecialNode) extractFunc).setPropagateFullCallNeededException(); } this.replaceCall = (RCallSpecialNode) createFunctionUpdate(source, extractFunc.asRSyntaxNode(), ReadVariableNode.create("*rhs*" + tempNamesStartIndex), calls.get(0), codeBuilderContext); - this.replaceCall.setPropagateFullCallNeededException(true); + this.replaceCall.setPropagateFullCallNeededException(); } @Override @@ -255,7 +254,7 @@ abstract class ReplacementNode extends OperatorNode { // shared, it could not be extracted from a shared container (list), so we should be // OK with not calling any other update function and just update the value directly. replaceCall.execute(frame); - } catch (FullCallNeededException | RecursiveSpecialBailout e) { + } catch (FullCallNeededException e) { CompilerDirectives.transferToInterpreterAndInvalidate(); replace(new GenericReplacementNode(getLazySourceSection(), operator, target, lhs, rhs, calls, targetVarName, isSuper, tempNamesStartIndex)).executeReplacement(frame); } @@ -295,10 +294,10 @@ abstract class ReplacementNode extends OperatorNode { RNode extractFunc = target; for (int i = calls.size() - 1; i >= 1; i--) { extractFunc = createSpecialFunctionQuery(calls.get(i), extractFunc.asRSyntaxNode(), codeBuilderContext); - ((RCallSpecialNode) extractFunc).setPropagateFullCallNeededException(true); + ((RCallSpecialNode) extractFunc).setPropagateFullCallNeededException(); } this.replaceCall = (RCallSpecialNode) createFunctionUpdate(source, extractFunc.asRSyntaxNode(), rhs.asRSyntaxNode(), calls.get(0), codeBuilderContext); - this.replaceCall.setPropagateFullCallNeededException(true); + this.replaceCall.setPropagateFullCallNeededException(); } @Override @@ -316,17 +315,16 @@ abstract class ReplacementNode extends OperatorNode { // shared, it could not be extracted from a shared container (list), so we should be // OK with not calling any other update function and just update the value directly. replaceCall.execute(frame); - } catch (FullCallNeededException | RecursiveSpecialBailout e) { + } catch (FullCallNeededException e) { CompilerDirectives.transferToInterpreterAndInvalidate(); GenericReplacementNode replacement = replace(new GenericReplacementNode(getLazySourceSection(), operator, target, lhs, rhs, calls, targetVarName, isSuper, tempNamesStartIndex)); - Object rhsValue = e instanceof FullCallNeededException ? ((FullCallNeededException) e).rhsValue : ((RecursiveSpecialBailout) e).rhsValue; - if (rhsValue == null) { + if (e.rhsValue == null) { // we haven't queried the rhs value yet replacement.voidExecute(frame); } else { // rhs was already queried, so pass it along - replacement.voidExecuteWithRhs(frame, rhsValue); + replacement.voidExecuteWithRhs(frame, e.rhsValue); } } } 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 472020d8bcd90a4d6b26db4d23e37fa2ec1496ae..e0c9f9eb525f116bfd2cf38921a8320f3e12bfb0 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 @@ -84,7 +84,7 @@ public final class FunctionExpressionNode extends RSourceSectionNode implements } initialized = true; } - RFunction func = RDataFactory.createFunction(RFunction.NO_NAME, callTarget, null, matFrame); + RFunction func = RDataFactory.createFunction(RFunction.NO_NAME, RFunction.NO_NAME, callTarget, null, matFrame); RInstrumentation.checkDebugRequested(func); return func; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java index 8259598aa45b9f78292eed86efc0d6672be9283c..830bf51331a185cf2cc207e1bc7c22577f1aace2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java @@ -22,8 +22,6 @@ */ package com.oracle.truffle.r.nodes.function; -import java.util.Arrays; - import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.frame.VirtualFrame; @@ -37,7 +35,6 @@ 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.builtins.RSpecialFactory.FullCallNeededException; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RPromise; @@ -98,7 +95,6 @@ final class PeekLocalVariableNode extends RNode implements RSyntaxLookup { public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode, RSyntaxCall { - private static final int NO_RECURSIVE_ARGUMENT_INDEX = -1; private static final boolean useSpecials = FastROptions.UseSpecials.getBooleanValue(); // currently cannot be RSourceSectionNode because of TruffleDSL restrictions @@ -129,12 +125,16 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode private final RFunction expectedFunction; /** - * If this instance is argument of another RCallSpecialNode (parent), then this will be the - * index into the parent arguments array, otherwise {@link #NO_RECURSIVE_ARGUMENT_INDEX}. + * If this is true, then any bailout should simply be forwarded by re-throwing the exception. */ - private int argumentIndex = NO_RECURSIVE_ARGUMENT_INDEX; private boolean propagateFullCallNeededException; + /** + * If this is non-null, then any bailout should lead to be forwarded by re-throwing the + * exception after replacing itself with a proper call node. + */ + private RCallSpecialNode callSpecialParent; + private RCallSpecialNode(SourceSection sourceSection, RNode functionNode, RFunction expectedFunction, RSyntaxNode[] arguments, ArgumentsSignature signature, RNode special) { this.sourceSectionR = sourceSection; this.expectedFunction = expectedFunction; @@ -206,7 +206,6 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode localArguments[i] = RContext.getASTBuilder().process(arguments[i]).asRNode(); } else { assert arguments[i] instanceof RCallSpecialNode; - ((RCallSpecialNode) arguments[i]).setArgumentIndex(i); localArguments[i] = arguments[i].asRNode(); } } @@ -219,7 +218,15 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode RFunction expectedFunction = RContext.lookupBuiltin(name); RInternalError.guarantee(expectedFunction != null); - return new RCallSpecialNode(sourceSection, functionNode, expectedFunction, arguments, signature, special); + RCallSpecialNode callSpecial = new RCallSpecialNode(sourceSection, functionNode, expectedFunction, arguments, signature, special); + for (int i = 0; i < arguments.length; i++) { + if (!inReplace || !contains(ignoredArguments, i)) { + if (arguments[i] instanceof RCallSpecialNode) { + ((RCallSpecialNode) arguments[i]).setCallSpecialParent(callSpecial); + } + } + } + return callSpecial; } private static boolean contains(int[] ignoredArguments, int index) { @@ -239,45 +246,30 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode throw RSpecialFactory.throwFullCallNeeded(); } return special.execute(frame); - } catch (RecursiveSpecialBailout bailout) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - throwOnRecursiveSpecial(bailout.rhsValue); - return replace(getRCallNode(rewriteSpecialArgument(bailout))).execute(frame, function); } catch (RSpecialFactory.FullCallNeededException e) { CompilerDirectives.transferToInterpreterAndInvalidate(); - throwOnRecursiveSpecial(e.rhsValue); - return replace(getRCallNode()).execute(frame, function); - } - } - - private void throwOnRecursiveSpecial(Object rhsValue) { - if (isRecursiveSpecial()) { - throw new RecursiveSpecialBailout(argumentIndex, rhsValue); + if (propagateFullCallNeededException) { + throw e; + } + RCallNode callNode = getRCallNode(); + for (RSyntaxElement arg : arguments) { + if (arg instanceof RCallSpecialNode) { + ((RCallSpecialNode) arg).setCallSpecialParent(null); + } + } + if (callSpecialParent != null) { + RSyntaxNode[] args = callSpecialParent.arguments; + for (int i = 0; i < args.length; i++) { + if (args[i] == this) { + args[i] = callNode; + } + } + throw e; + } + return replace(callNode).execute(frame, function); } } - private RSyntaxNode[] rewriteSpecialArgument(RecursiveSpecialBailout bailout) { - // Note: other arguments that may be specials too, stay specials, their parent node will be - // changed in createRCallNode, but we are never going to use the original parent, which is - // the 'this.special' node that bailed out. - // Note 2: we have to make a copy of the array, because this node may have been shallow - // copied and the other copy will keep its copied parent, i.e. bailout exception from here - // will not reach the copied parent, but we would rewrite one of its arguments to full-blown - // RCallNode. It seems that bailing out happens less frequently than Node.copy, so we do the - // copying here. - RSyntaxNode[] newArguments = Arrays.copyOf(arguments, arguments.length); - RCallSpecialNode arg = (RCallSpecialNode) arguments[bailout.argumentIndex]; - newArguments[bailout.argumentIndex] = arg.getRCallNode(); - return newArguments; - } - - private boolean isRecursiveSpecial() { - // Note: we need to check the parent's parent, because it might have been rewritten by - // bailout of some of its other arguments. If parent is special node, then its parent must - // be RCallSpecialNode - return propagateFullCallNeededException || (argumentIndex != NO_RECURSIVE_ARGUMENT_INDEX && getParent() != null && getParent().getParent() instanceof RCallSpecialNode); - } - private RCallNode getRCallNode(RSyntaxNode[] newArguments) { return RCallNode.createCall(sourceSectionR, functionNode == null ? null : functionNode.getValueNode(), signature, newArguments); } @@ -286,16 +278,18 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode return getRCallNode(arguments); } - private void setArgumentIndex(int index) { - argumentIndex = index; + /** + * see {@link #propagateFullCallNeededException}. + */ + public void setPropagateFullCallNeededException() { + propagateFullCallNeededException = true; } /** - * If set to {@code true} the special call will raise {@link FullCallNeededException} even when - * the parent is a special call. + * see {@link #callSpecialParent}. */ - public void setPropagateFullCallNeededException(boolean flag) { - propagateFullCallNeededException = flag; + private void setCallSpecialParent(RCallSpecialNode call) { + callSpecialParent = call; } @Override @@ -318,20 +312,4 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode public RSyntaxElement[] getSyntaxArguments() { return arguments == null ? new RSyntaxElement[]{RSyntaxLookup.createDummyLookup(RSyntaxNode.LAZY_DEPARSE, "...", false)} : arguments; } - - @SuppressWarnings("serial") - public static final class RecursiveSpecialBailout extends RuntimeException { - public final int argumentIndex; - public final Object rhsValue; - - RecursiveSpecialBailout(int argumentIndex, Object rhsValue) { - this.argumentIndex = argumentIndex; - this.rhsValue = rhsValue; - } - - @Override - public synchronized Throwable fillInStackTrace() { - return null; - } - } } diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java index add58098c44adde2a5b5cd6009911202cb70cba0..1d30f22faf20deb7d9dd2c68968074ed78a48ebc 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java @@ -1156,7 +1156,7 @@ public class CallRFFIHelper { try { Source source = RSource.fromTextInternal(textString, RSource.Internal.R_PARSEVECTOR); - RExpression exprs = RContext.getEngine().parse(null, source); + RExpression exprs = RContext.getEngine().parse(source); return new ParseResult(ParseStatus.PARSE_OK.ordinal(), exprs); } catch (ParseException ex) { // TODO incomplete 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 5f598c263380b50b2a8d638beb849e10db61191d..f0005b639aa32fc19806700f8fc22b15120367ad 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 @@ -49,7 +49,6 @@ public enum FastROptions { LoadBase("Load base package", true), PrintComplexLookups("Print a message for each non-trivial variable lookup", 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), UseInternalGraphics("Whether the internal (Java) graphics subsystem should be used", false), diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/HasSignature.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/HasSignature.java index ae2c743fbe29e0bc890841abc4a6f4896f9c0096..7ae86acaf1f35dba75a77d4895a44a81a8c4ab25 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/HasSignature.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/HasSignature.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 @@ -22,6 +22,10 @@ */ package com.oracle.truffle.r.runtime; +import com.oracle.truffle.api.RootCallTarget; + public interface HasSignature { ArgumentsSignature getSignature(); + + RootCallTarget duplicateWithNewFrameDescriptor(); } 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 0fec763e0e56036ee7fb48ae964ffcfafebab476..37282478572cb84bfb6ea1a8196b73037f5bccbe 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,14 +23,12 @@ 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.RootCallTarget; 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; @@ -38,18 +36,19 @@ 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.RPromise.Closure; +import com.oracle.truffle.r.runtime.data.RPromise.PromiseState; import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RUnboundValue; 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.REnvTruffleFrameAccess; -import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; /** * Implementation of a channel abstraction used for communication between parallel contexts in @@ -272,9 +271,9 @@ public class RChannel { private final Object env; private final Object value; - private final byte[] serializedExpr; + private final RSyntaxElement serializedExpr; - public SerializedPromise(Object env, Object value, byte[] serializedExpr) { + public SerializedPromise(Object env, Object value, RSyntaxElement serializedExpr) { this.env = env; this.value = value; this.serializedExpr = serializedExpr; @@ -288,7 +287,7 @@ public class RChannel { return value; } - public byte[] getSerializedExpr() { + public RSyntaxElement getSerializedExpr() { return serializedExpr; } @@ -297,9 +296,9 @@ public class RChannel { protected static class SerializedFunction { private final RAttributes attributes; private final Object env; - private final byte[] serializedDef; + private final RFunction serializedDef; - public SerializedFunction(RAttributes attributes, Object env, byte[] serializedDef) { + public SerializedFunction(RAttributes attributes, Object env, RFunction serializedDef) { this.attributes = attributes; this.env = env; this.serializedDef = serializedDef; @@ -313,7 +312,7 @@ public class RChannel { return env; } - public byte[] getSerializedDef() { + public RFunction getSerializedDef() { return serializedDef; } } @@ -417,22 +416,20 @@ public class RChannel { 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); + return new SerializedPromise(RNull.instance, p.getValue(), p.getClosure().getExpr().asRSyntaxNode()); } else { REnvironment env = p.getFrame() == null ? REnvironment.globalEnv() : REnvironment.frameToEnvironment(p.getFrame()); - return new SerializedPromise(convertPrivate(env), RUnboundValue.instance, serializedPromiseRep); + return new SerializedPromise(convertPrivate(env), RUnboundValue.instance, p.getClosure().getExpr().asRSyntaxNode()); } } 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); + return new SerializedFunction(attributes == null ? null : createShareableSlow(attributes, true), env, fn); } private Object convertPrivateAttributable(Object msg) throws IOException { @@ -629,27 +626,28 @@ public class RChannel { @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); + Closure closure = Closure.create(RContext.getASTBuilder().process(p.getSerializedExpr()).asRNode()); + if (p.getValue() == RUnboundValue.instance) { + Object environment = p.getEnv(); + if (environment != RNull.instance) { + environment = unserializeObject(environment); + } + REnvironment env = environment == RNull.instance ? REnvironment.baseEnv() : (REnvironment) environment; + return RDataFactory.createPromise(PromiseState.Explicit, closure, env.getFrame()); + } else { + return RDataFactory.createEvaluatedPromise(closure, p.getValue()); } - return RSerialize.unserializePromise(expr, env, p.getValue()); } @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); + RFunction fun = f.getSerializedDef(); 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); + HasSignature root = (HasSignature) fun.getTarget().getRootNode(); + RootCallTarget target = root.duplicateWithNewFrameDescriptor(); + FrameSlotChangeMonitor.initializeEnclosingFrame(target.getRootNode().getFrameDescriptor(), enclosingFrame); + RFunction fn = RDataFactory.createFunction(fun.getName(), fun.getPackageName(), target, null, enclosingFrame); RAttributes attributes = f.getAttributes(); if (attributes != null) { assert fn.getAttributes() == null; @@ -685,11 +683,11 @@ public class RChannel { 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) + /* + * 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); } } 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 81bedb07ca94d3596a40f79a3ad038db89f924f2..8c0c3cbeb5949584fa1086469c6f9a6e2531cb23 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 @@ -15,9 +15,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; -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; @@ -43,6 +41,7 @@ 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.RTypedValue; +import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -58,18 +57,6 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor; /** * Deparsing R objects. - * - * There are two distinct clients of this class: - * <ul> - * <li>{@code RSerialize} when it needs to convert an unserialized GnuR {@code pairlist} instance - * that denotes a closure into an {@link RFunction} which is, currently, done by deparsing and - * reparsing the value.</li> - * <li>The {@code deparse} builtin.</li> - * </ul> - * - * Much of the code here is related to case 1, which would be unnecessary if unserialize created - * ASTs for language elements directly rather than via deparse/parse. The deparsing of ASTs is - * handled in {@code RASTDeparse} via the {@link RRuntimeASTAccess} interface. */ public class RDeparse { @@ -161,7 +148,7 @@ public class RDeparse { } } - @CompilationFinal private static final Func[] FUNCTAB = new Func[]{ + private static final Func[] FUNCTAB = new Func[]{ new Func("+", null, new PPInfo(PP.BINARY, PREC_SUM, false)), new Func("-", null, new PPInfo(PP.BINARY, PREC_SUM, false)), new Func("*", null, new PPInfo(PP.BINARY, PREC_PROD, false)), @@ -223,16 +210,6 @@ public class RDeparse { return len > 0 && op.charAt(0) == '%' && op.charAt(len - 1) == '%'; } - /** - * Ensure that {@code node} has a {@link SourceSection} by deparsing if necessary. - */ - public static void ensureSourceSection(RSyntaxElement node) { - SourceSection ss = node.getLazySourceSection(); - if (ss == RSyntaxNode.LAZY_DEPARSE) { - new DeparseVisitor(true, RDeparse.MAX_Cutoff, false, -1, 0, null).append(node).fixupSources(); - } - } - private static Func isInfixOperatorNode(RSyntaxElement element) { if (element instanceof RSyntaxCall) { RSyntaxElement lhs = ((RSyntaxCall) element).getSyntaxLHS(); @@ -285,14 +262,11 @@ public class RDeparse { private int indent = 0; private int lastLineStart = 0; - private final Map<String, Object> constants; - - DeparseVisitor(boolean storeSource, int cutoff, boolean backtick, int opts, int nlines, Map<String, Object> constants) { + DeparseVisitor(boolean storeSource, int cutoff, boolean backtick, int opts, int nlines) { this.cutoff = cutoff; this.backtick = backtick; this.opts = opts; this.nlines = nlines; - this.constants = constants; this.sources = storeSource ? new ArrayList<>() : null; } @@ -564,71 +538,9 @@ public class RDeparse { } @Override - @SuppressWarnings("try") protected Void visit(RSyntaxConstant constant) { // coerce scalar values to vectors and unwrap data frames and factors: - Object value = RRuntime.asAbstractVector(constant.getValue()); - - if (constants != null && !(value instanceof RAbstractVector || value instanceof RNull)) { - String name = "C.." + constants.size(); - constants.put(name, value); - append(name); - return null; - } - - if (value instanceof RExpression) { - append("expression(").appendListContents((RExpression) value).append(')'); - } else if (value instanceof RAbstractListVector) { - RAbstractListVector obj = (RAbstractListVector) value; - try (C c = withAttributes(obj)) { - append("list(").appendListContents(obj).append(')'); - } - } else if (value instanceof RAbstractVector) { - RAbstractVector obj = (RAbstractVector) value; - try (C c = withAttributes(obj)) { - appendVector((RAbstractVector) value); - } - } else if (value instanceof RNull) { - append("NULL"); - } else if (value instanceof RFunction) { - RFunction f = (RFunction) value; - if (f.isBuiltin()) { - append(".Primitive(\"").append(f.getName()).append("\")"); - } else { - append(RContext.getRRuntimeASTAccess().getSyntaxFunction(f)); - } - } else if (value instanceof RPairList) { - RPairList pl = (RPairList) value; - assert pl.getType() == SEXPTYPE.LISTSXP; - append("pairlist("); - Arguments<RSyntaxElement> arguments = wrapArguments(pl); - appendArgs(arguments.getSignature(), arguments.getArguments(), 0, false); - append(')'); - } else if (value instanceof RS4Object) { - RS4Object s4Obj = (RS4Object) value; - Object clazz = s4Obj.getAttr("class"); - String className = clazz == null ? "S4" : RRuntime.toString(RRuntime.asStringLengthOne(clazz)); - append("new(\"").append(className).append('\"'); - try (C c = indent()) { - printline(); - if (s4Obj.getAttributes() != null) { - for (RAttribute att : s4Obj.getAttributes()) { - if (!"class".equals(att.getName())) { - append(", ").append(att.getName()).append(" = ").process(att.getValue()).printline(); - } - } - } - } - append(')'); - } else if (value instanceof RExternalPtr) { - 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); - } + appendConstant(constant.getValue()); return null; } @@ -644,24 +556,10 @@ public class RDeparse { @Override protected Void visit(RSyntaxFunction function) { - append("function ("); + append("function("); appendArgs(function.getSyntaxSignature(), function.getSyntaxArgumentDefaults(), 0, true); append(") "); - RSyntaxElement body = function.getSyntaxBody(); - boolean newline = true; - if (body instanceof RSyntaxCall) { - RSyntaxCall c = (RSyntaxCall) body; - if (c.getSyntaxLHS() instanceof RSyntaxLookup) { - RSyntaxLookup l = (RSyntaxLookup) c.getSyntaxLHS(); - if ("{".equals(l.getIdentifier())) { - newline = false; - } - } - } - if (newline) { - printline(); - } - append(body); + appendFunctionBody(function.getSyntaxBody()); return null; } } @@ -669,7 +567,10 @@ public class RDeparse { private void appendWithParens(RSyntaxElement arg, PPInfo mainOp, boolean isLeft) { Func func = isInfixOperatorNode(arg); boolean needsParens = false; - if (func != null) { + if (func == null) { + // put parens around complex values + needsParens = !isLeft && arg instanceof RSyntaxConstant && ((RSyntaxConstant) arg).getValue() instanceof RAbstractComplexVector; + } else { PPInfo arginfo = func.info; switch (arginfo.kind) { case ASSIGN: @@ -713,22 +614,112 @@ public class RDeparse { } } + @SuppressWarnings("try") + private DeparseVisitor appendConstant(Object originalValue) { + Object value = RRuntime.asAbstractVector(originalValue); + if (value instanceof RExpression) { + append("expression(").appendListContents((RExpression) value).append(')'); + } else if (value instanceof RAbstractListVector) { + RAbstractListVector obj = (RAbstractListVector) value; + try (C c = withAttributes(obj)) { + append("list(").appendListContents(obj).append(')'); + } + } else if (value instanceof RAbstractVector) { + RAbstractVector obj = (RAbstractVector) value; + try (C c = withAttributes(obj)) { + appendVector((RAbstractVector) value); + } + } else if (value instanceof RNull) { + append("NULL"); + } else if (value instanceof RFunction) { + RFunction f = (RFunction) value; + if (f.isBuiltin()) { + append(".Primitive(\"").append(f.getName()).append("\")"); + } else { + RSyntaxFunction function = (RSyntaxFunction) f.getRootNode(); + append("function ("); + appendArgs(function.getSyntaxSignature(), function.getSyntaxArgumentDefaults(), 0, true); + append(") "); + appendFunctionBody(function.getSyntaxBody()); + } + } else if (value instanceof RPairList) { + RPairList arglist = (RPairList) value; + assert arglist.getType() == SEXPTYPE.LISTSXP; + append("pairlist("); + int i = 0; + boolean lbreak = false; + while (arglist != null) { + if (i++ > 0) { + append(", "); + } + lbreak = linebreak(lbreak); + if (arglist.getTag() != RNull.instance) { + String argName = ((RSymbol) arglist.getTag()).getName(); + if (!argName.isEmpty()) { + append(argName).append(" = "); + } + } + appendValue(arglist.car()); + + arglist = next(arglist); + } + append(')'); + } else if (value instanceof RS4Object) { + RS4Object s4Obj = (RS4Object) value; + Object clazz = s4Obj.getAttr("class"); + String className = clazz == null ? "S4" : RRuntime.toString(RRuntime.asStringLengthOne(clazz)); + append("new(\"").append(className).append('\"'); + try (C c = indent()) { + printline(); + if (s4Obj.getAttributes() != null) { + for (RAttribute att : s4Obj.getAttributes()) { + if (!"class".equals(att.getName())) { + append(", ").append(att.getName()).append(" = ").appendValue(att.getValue()).printline(); + } + } + } + } + append(')'); + } else if (value instanceof RExternalPtr) { + 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); + } + return this; + } + + private DeparseVisitor appendFunctionBody(RSyntaxElement body) { + boolean newline = true; + if (body instanceof RSyntaxCall) { + RSyntaxCall c = (RSyntaxCall) body; + if (c.getSyntaxLHS() instanceof RSyntaxLookup) { + RSyntaxLookup l = (RSyntaxLookup) c.getSyntaxLHS(); + if ("{".equals(l.getIdentifier())) { + newline = false; + } + } + } + if (newline) { + printline(); + } + return append(body); + } + private DeparseVisitor appendArgs(ArgumentsSignature signature, RSyntaxElement[] args, int start, boolean formals) { boolean lbreak = false; for (int i = start; i < args.length; i++) { + if (i > start) { + append(", "); + } lbreak = linebreak(lbreak); RSyntaxElement argument = args[i]; - if (argument instanceof RSyntaxLookup && ((RSyntaxLookup) argument).getIdentifier().isEmpty()) { - argument = null; - } - if (argument instanceof RSyntaxConstant && ((RSyntaxConstant) argument).getValue() instanceof REmpty) { - argument = null; - } String name = signature.getName(i); - if (name != null && name.isEmpty()) { - name = null; - } - if (name != null) { + + if (name != null && !name.isEmpty()) { if (isValidName(name)) { append(name); } else { @@ -739,11 +730,14 @@ public class RDeparse { } } if (argument != null) { + if (argument instanceof RSyntaxLookup && ((RSyntaxLookup) argument).getIdentifier().isEmpty()) { + continue; + } + if (argument instanceof RSyntaxConstant && ((RSyntaxConstant) argument).getValue() instanceof REmpty) { + continue; + } append(argument); } - if (i != args.length - 1) { - append(", "); - } } if (lbreak) { indent--; @@ -751,100 +745,31 @@ public class RDeparse { return this; } - private DeparseVisitor process(Object v) { + private DeparseVisitor appendValue(Object v) { assert v != null; - assert RRuntime.asAbstractVector(v) instanceof RTypedValue : v.getClass(); assert !(v instanceof RSyntaxElement) : v.getClass(); - RSyntaxElement element = wrap(v, false); - if (!quoteExpressions() || element instanceof RSyntaxConstant) { - append(element); - } else { - append("quote("); - append(element); - append(')'); - } - return this; - } - - private static RSyntaxElement wrap(Object v, boolean isCallLHS) { Object value = RRuntime.asAbstractVector(v); + assert value instanceof RTypedValue : v.getClass(); + + RSyntaxElement element; if (value instanceof RSymbol) { - return RSyntaxLookup.createDummyLookup(RSyntaxNode.INTERNAL, ((RSymbol) value).getName(), isCallLHS); + element = RSyntaxLookup.createDummyLookup(RSyntaxNode.INTERNAL, ((RSymbol) value).getName(), false); } else if (value instanceof RLanguage) { - return ((RLanguage) value).getRep().asRSyntaxNode(); - } else if (value instanceof RPairList) { - RPairList pl = (RPairList) value; - switch (pl.getType()) { - case LANGSXP: - return wrapCall(pl); - case CLOSXP: - return wrapFunctionExpression(pl); - default: - throw RInternalError.shouldNotReachHere("sexptype: " + pl.getType()); - } + element = ((RLanguage) value).getRep().asRSyntaxNode(); } else if (value instanceof RMissing) { - return RSyntaxLookup.createDummyLookup(null, "", false); + element = RSyntaxLookup.createDummyLookup(null, "", false); } else { - return RSyntaxConstant.createDummyConstant(null, value); - } - } - - private static RSyntaxElement wrapCall(RPairList pl) { - Object car = pl.car(); - if (car instanceof RSymbol && ((RSymbol) car).getName().equals("function")) { - RPairList fun = (RPairList) pl.cdr(); - return wrapFunctionExpression(fun); + return appendConstant(value); } - RSyntaxElement lhs = wrap(car, true); - - Arguments<RSyntaxElement> args = wrapArguments(pl.cdr()); - return RSyntaxCall.createDummyCall(null, lhs, args.getSignature(), args.getArguments()); - } - - private static RSyntaxElement wrapFunctionExpression(RPairList fun) { - // assert fun.getTag() == RNull.instance : "function expression with non-null - // environment"; - Arguments<RSyntaxElement> args = wrapArguments(fun.car()); - RSyntaxElement body; - Object cdr = fun.cdr(); - if (cdr instanceof RPairList) { - RPairList pl = (RPairList) cdr; - if (pl.getType() == SEXPTYPE.BCODESXP) { - RAbstractListVector list = (RAbstractListVector) fun.cddr(); - body = wrap(list.getDataAtAsObject(0), false); - } else if (pl.getType() == SEXPTYPE.LISTSXP) { - assert pl.cdr() == RNull.instance || (pl.cadr() == RNull.instance && pl.cddr() == RNull.instance); - body = wrap(pl.car(), false); - } else { - assert pl.getType() == SEXPTYPE.LANGSXP; - body = wrap(pl, false); - } + if (!quoteExpressions() || element instanceof RSyntaxConstant) { + append(element); } else { - body = wrap(cdr, false); - } - - return RSyntaxFunction.createDummyFunction(null, args.getSignature(), args.getArguments(), body, null); - } - - private static Arguments<RSyntaxElement> wrapArguments(Object args) { - RPairList arglist = args instanceof RNull ? null : (RPairList) args; - ArrayList<RSyntaxElement> argElements = new ArrayList<>(); - ArrayList<String> argNames = new ArrayList<>(); - while (arglist != null) { - Object argTag = arglist.getTag(); - if (argTag != null && argTag != RNull.instance) { - String rs = ((RSymbol) arglist.getTag()).getName(); - argNames.add(rs); - } else { - argNames.add(null); - } - argElements.add(wrap(arglist.car(), false)); - arglist = next(arglist); + append("quote("); + append(element); + append(')'); } - RSyntaxElement[] arguments = argElements.toArray(new RSyntaxElement[argElements.size()]); - ArgumentsSignature signature = ArgumentsSignature.get(argNames.toArray(new String[argNames.size()])); - return Arguments.create(arguments, signature); + return this; } private static RPairList next(RPairList pairlist) { @@ -952,12 +877,11 @@ public class RDeparse { append(", "); } lbreak = linebreak(lbreak); - String sname = snames == null ? null : snames.getDataAt(i); - if (snames != null && ((sname = snames.getDataAt(i)) != null)) { - append(sname); + if (snames != null) { + append(snames.getDataAt(i)); append(" = "); } - append(wrap(v.getDataAtAsObject(i), false)); + appendValue(v.getDataAtAsObject(i)); } if (lbreak) { indent--; @@ -1021,7 +945,7 @@ public class RDeparse { append(dotName); } append(" = "); - process(attr.getValue()); + appendValue(attr.getValue()); append(')'); } } @@ -1033,36 +957,30 @@ public class RDeparse { } } - /** - * Version for use by {@code RSerialize} to convert a CLOSXP/LANGSXP/PROMSXP into a parseable - * string. - */ - @TruffleBoundary - public static String deparseDeserialize(Map<String, Object> constants, Object obj) { - Object root = obj; - if (root instanceof RPairList) { - RPairList pl = (RPairList) root; - if (pl.getType() == SEXPTYPE.BCODESXP) { - RAbstractListVector list = (RAbstractListVector) pl.cdr(); - root = list.getDataAtAsObject(0); - } - } - return new DeparseVisitor(false, 80, true, SHOWATTRIBUTES, -1, constants).process(root).getContents(); - } - @TruffleBoundary public static String deparseSyntaxElement(RSyntaxElement element) { - return new DeparseVisitor(false, RDeparse.MAX_Cutoff, true, 0, -1, null).append(element).getContents(); + return new DeparseVisitor(false, RDeparse.MAX_Cutoff, true, 0, -1).append(element).getContents(); } @TruffleBoundary - public static String deparse(Object expr) { - return new DeparseVisitor(false, RDeparse.MAX_Cutoff, true, 0, -1, null).process(expr).getContents(); + public static String deparse(Object value) { + return new DeparseVisitor(false, RDeparse.MAX_Cutoff, true, 0, -1).appendValue(value).getContents(); } @TruffleBoundary public static String deparse(Object expr, int cutoff, boolean backtick, int opts, int nlines) { - return new DeparseVisitor(false, cutoff, backtick, opts, nlines, null).process(expr).getContents(); + return new DeparseVisitor(false, cutoff, backtick, opts, nlines).appendValue(expr).getContents(); + } + + /** + * Ensure that {@code node} has a {@link SourceSection} by deparsing if necessary. + */ + public static void ensureSourceSection(RSyntaxNode node) { + SourceSection ss = node.getLazySourceSection(); + if (ss == RSyntaxNode.LAZY_DEPARSE) { + new DeparseVisitor(true, RDeparse.MAX_Cutoff, false, -1, 0).append(node).fixupSources(); + assert node.getLazySourceSection() != RSyntaxNode.LAZY_DEPARSE; + } } private static String quotify(String name, char qc) { @@ -1073,7 +991,7 @@ public class RDeparse { sb.append(qc); for (int i = 0; i < name.length(); i++) { char ch = name.charAt(i); - if (ch == '\\') { + if (ch == '\\' || ch == '`') { sb.append(ch); } sb.append(ch); @@ -1086,10 +1004,6 @@ public class RDeparse { private static final HashSet<String> keywords = new HashSet<>(Arrays.asList("NULL", "NA", "TRUE", "FALSE", "Inf", "NaN", "NA_integer_", "NA_real_", "NA_character_", "NA_complex_", "function", "while", "repeat", "for", "if", "in", "else", "next", "break", "...")); - private static boolean isKeyword(String name) { - return keywords.contains(name); - } - public static boolean isValidName(String name) { char ch = safeCharAt(name, 0); if (ch != '.' && !Character.isLetter(ch)) { @@ -1110,7 +1024,7 @@ public class RDeparse { if (name.equals("...")) { return true; } - if (isKeyword(name)) { + if (keywords.contains(name)) { return false; } return true; 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 dc57b2b69c7cb57f9e09908765a1bbb1328e7d20..f47dda016857a979b6e7ece30d3ffc88a381de07 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 @@ -23,7 +23,6 @@ package com.oracle.truffle.r.runtime; -import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -60,7 +59,7 @@ public final class RInternalCode { private REnvironment evaluate() { try { - RExpression parsedCode = context.getThisEngine().parse(Collections.emptyMap(), source); + RExpression parsedCode = context.getThisEngine().parse(source); REnvironment statsPackage = REnvironment.getRegisteredNamespace(context, basePackage); evaluatedEnvironment = RDataFactory.createNewEnv(null, true, 10); evaluatedEnvironment.setParent(statsPackage); 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 db3d5c223ea2a3d048d1c06c8e9f4e46487d0262..7a4a01cd501f6eca13e219621a21fff3466dc094 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 @@ -192,4 +192,6 @@ public interface RRuntimeASTAccess { String encodeComplex(RComplex x, int digits); + void checkDebugRequest(RFunction func); + } 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 d0817ba5237595ce31d44d938e5f70d1e61ec27c..5d7fa9e54034542e95439baf6d3b45d637edd077 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 @@ -13,29 +13,28 @@ package com.oracle.truffle.r.runtime; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileWriter; 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.ArrayList; import java.util.Arrays; import java.util.Deque; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.WeakHashMap; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.frame.MaterializedFrame; -import com.oracle.truffle.api.source.Source; import com.oracle.truffle.r.runtime.conn.RConnection; -import com.oracle.truffle.r.runtime.context.Engine.ParseException; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RAttributable; @@ -67,14 +66,18 @@ import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.data.RUnboundValue; import com.oracle.truffle.r.runtime.data.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.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; -import com.oracle.truffle.r.runtime.instrument.RPackageSource; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; +import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; @@ -187,7 +190,7 @@ public class RSerialize { * {@code true} iff we are saving the source from the deparse of an unserialized function * (for debugging later). */ - private boolean saveDeparse; + boolean saveDeparse; /** * {@code ...getNamespace} in "namespace.R", used to callback to handle a @@ -324,26 +327,6 @@ 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; @@ -360,13 +343,9 @@ public class RSerialize { protected String functionName; /** - * We need to know whether we are unserializing a {@link SEXPTYPE#CLOSXP} as we do not want - * convert embedded instances of {@link SEXPTYPE#LANGSXP} into ASTs. - */ - private int closureDepth; - /** - * For formula, the same logic applies as we only want to convert to an RFormula when - * langDepth is zero. + * We need to know whether we are unserializing a {@link SEXPTYPE#CLOSXP}, + * {@link SEXPTYPE#LANGSXP} or {@link SEXPTYPE#PROMSXP} as we do not want convert embedded + * instances of {@link SEXPTYPE#LANGSXP} into ASTs. */ private int langDepth; @@ -382,7 +361,6 @@ public class RSerialize { super(hook); this.packageName = packageName; this.functionName = functionName; - this.closureDepth = 0; byte[] buf = new byte[2]; is.read(buf); switch (buf[0]) { @@ -430,9 +408,8 @@ public class RSerialize { private void incDepth(SEXPTYPE type) { switch (type) { case CLOSXP: - closureDepth++; - break; case LANGSXP: + case PROMSXP: langDepth++; break; default: @@ -565,21 +542,11 @@ public class RSerialize { } Object carItem = readItem(); Object cdrItem = readItem(); - RPairList pairList = RDataFactory.createPairList(carItem, cdrItem, tagItem, type); - result = pairList; - if (attrItem != RNull.instance) { - /* - * TODO Currently we are losing attributes on CLOSXP (and LANGSXP) objects - * because this code places the attributes on the pairList and not on the - * RFunction object we eventually convert the pairlist into. - */ - setAttributes(pairList, attrItem); - } // Unlike GnuR the different types require some special treatment switch (type) { case CLOSXP: { - closureDepth--; + langDepth--; /* * Must convert the RPairList to a FastR AST. We could convert to an AST * directly, but it is easier and more robust to deparse and reparse. @@ -587,27 +554,19 @@ public class RSerialize { * level or not (and they are not always at the top in the default * packages) */ - RPairList rpl = (RPairList) result; if (FastROptions.debugMatches("printUclosure")) { - Debug.printClosure(rpl); + RPairList pairList = RDataFactory.createPairList(carItem, cdrItem, tagItem, type); + result = pairList; + if (attrItem != RNull.instance) { + setAttributes(pairList, attrItem); + } + Debug.printClosure(pairList); } - Map<String, Object> constants = new HashMap<>(); - String deparse = RDeparse.deparseDeserialize(constants, rpl); - try { - /* - * The tag of result is the enclosing environment (from - * NAMESPACESEXP) for the function. However the namespace is locked, - * so can't just eval there (and overwrite the promise), so we fix - * the enclosing frame up on return. - */ - MaterializedFrame enclosingFrame = ((REnvironment) rpl.getTag()).getFrame(); - RFunction func = parseFunction(constants, deparse, enclosingFrame, currentFunctionName); - - RAttributes.copyAttributes(func, rpl.getAttributes()); - result = func; - } catch (Throwable ex) { - throw new RInternalError(ex, "unserialize - failed to eval deparsed closure"); + RFunction func = PairlistDeserializer.processFunction(carItem, cdrItem, tagItem, currentFunctionName, packageName); + if (attrItem != RNull.instance) { + setAttributes(func, attrItem); } + result = func; break; } @@ -619,61 +578,69 @@ public class RSerialize { * the CLOSXP case, the entire structure is deparsed at the end. Ditto * for LANGSXP when specifying a formula */ - if (closureDepth == 0 && langDepth == 0) { - RPairList pl = (RPairList) result; - Map<String, Object> constants = new HashMap<>(); - String deparse = RDeparse.deparseDeserialize(constants, pl); - RExpression expr = parse(constants, deparse); - assert expr.getLength() == 1; - result = expr.getDataAt(0); - RAttributes attrs = pl.getAttributes(); - if (result instanceof RAttributable) { - RAttributes.copyAttributes((RAttributable) result, attrs); + if (langDepth == 0) { + RLanguage lang = PairlistDeserializer.processLanguage(carItem, cdrItem, tagItem); + if (attrItem != RNull.instance) { + setAttributes(lang, attrItem); + } + result = lang; + } else { + RPairList pairList = RDataFactory.createPairList(carItem, cdrItem, tagItem, type); + result = pairList; + if (attrItem != RNull.instance) { + setAttributes(pairList, attrItem); } } break; } case PROMSXP: { - RPairList pl = (RPairList) result; + langDepth--; /* * tag: environment for eval (or RNull if evaluated), car: value: * RUnboundValue if not evaluated, cdr: expression */ - Map<String, Object> constants = new HashMap<>(); - String deparse = RDeparse.deparseDeserialize(constants, pl.cdr()); - RExpression expr = parse(constants, deparse); - assert expr.getLength() == 1; - result = unserializePromise(expr, pl.getTag(), pl.car()); + result = PairlistDeserializer.processPromise(carItem, cdrItem, tagItem); break; } case DOTSXP: { - RPairList pl = (RPairList) result; - int len = pl.getLength(); + RPairList pairList = RDataFactory.createPairList(carItem, cdrItem, tagItem, type); + int len = pairList.getLength(); Object[] values = new Object[len]; String[] names = new String[len]; for (int i = 0; i < len; i++) { - values[i] = pl.car(); - if (pl.getTag() != RNull.instance) { - names[i] = ((RSymbol) pl.getTag()).getName(); + values[i] = pairList.car(); + if (pairList.getTag() != RNull.instance) { + names[i] = ((RSymbol) pairList.getTag()).getName(); } if (i < len - 1) { - pl = (RPairList) pl.cdr(); + pairList = (RPairList) pairList.cdr(); } } return new RArgsValuesAndNames(values, ArgumentsSignature.get(names)); } case LISTSXP: + RPairList pairList = RDataFactory.createPairList(carItem, cdrItem, tagItem, type); + result = pairList; + if (attrItem != RNull.instance) { + /* + * TODO Currently we are losing attributes on CLOSXP (and LANGSXP) + * objects because this code places the attributes on the pairList + * and not on the RFunction object we eventually convert the + * pairlist into. + */ + setAttributes(pairList, attrItem); + } break; } - if (!(result instanceof RScalar)) { - ((RTypedValue) result).setGPBits(levs); - } else { - // for now we only record S4-ness here, and in this case it shoud be 0 + if (result instanceof RScalar) { + // for now we only record S4-ness here, and in this case it should be 0 assert (levs == 0); + } else { + ((RTypedValue) result).setGPBits(levs); } return checkResult(result); } @@ -867,80 +834,6 @@ public class RSerialize { return result; } - private RExpression parse(Map<String, Object> constants, String deparseRaw) throws IOException { - try { - Source source = RSource.fromPackageTextInternal(deparseRaw, packageName); - return RContext.getEngine().parse(constants, source); - } catch (Throwable ex) { - /* - * Denotes a deparse/eval error, which is an unrecoverable bug, except in the - * special case where we are just saving package sources. - */ - saveDeparseResult(deparseRaw, true); - if (!contextState.saveDeparse) { - throw new RInternalError(ex, "internal deparse error - see file DEPARSE_ERROR"); - } else { - return null; - } - } - } - - private RFunction parseFunction(Map<String, Object> constants, String deparseRaw, MaterializedFrame enclosingFrame, String currentFunctionName) throws IOException { - try { - String sourcePath = null; - String deparse = deparseRaw; - /* - * To disambiguate identical saved deparsed files in different packages add a header - * line - */ - deparse = "# deparsed from package: " + packageName + "\n" + deparse; - if (contextState.saveDeparse) { - saveDeparseResult(deparse, false); - } else { - sourcePath = RPackageSource.lookup(deparse); - } - Source source; - String name; - if (sourcePath == null) { - source = RSource.fromPackageTextInternalWithName(deparse, packageName, currentFunctionName); - name = currentFunctionName; - } else { - source = RSource.fromFileName(deparse, sourcePath); - // Located a function source file from which we can retrieve the function name - name = RPackageSource.decodeName(sourcePath); - } - return RContext.getEngine().parseFunction(constants, name, source, enclosingFrame); - } catch (Throwable ex) { - /* - * Denotes a deparse/eval error, which is an unrecoverable bug, except in the - * special case where we are just saving package sources. - */ - saveDeparseResult(deparseRaw, true); - if (!contextState.saveDeparse) { - throw new RInternalError(ex, "internal deparse error - see file DEPARSE_ERROR"); - } else { - try { - return RContext.getEngine().parseFunction(constants, "", FAILED_DEPARSE_FUNCTION_SOURCE, enclosingFrame); - } catch (ParseException e) { - throw RInternalError.shouldNotReachHere(); - } - } - } - } - - private void saveDeparseResult(String deparse, boolean isError) throws IOException { - if (contextState.saveDeparse) { - RPackageSource.deparsed(deparse, isError); - } else if (isError) { - try (FileWriter wr = new FileWriter(new File(new File(REnvVars.rHome()), "DEPARSE" + (isError ? "_ERROR" : "")))) { - wr.write(deparse); - } - } - } - - private static final String FAILED_DEPARSE_FUNCTION = "function(...) stop(\"FastR error: proxy for lazily loaded function that did not deparse/parse\")"; - private static final Source FAILED_DEPARSE_FUNCTION_SOURCE = RSource.fromTextInternal(FAILED_DEPARSE_FUNCTION, RSource.Internal.DEPARSE_ERROR); - /** * GnuR uses a pairlist to represent attributes, whereas FastR uses the abstract RAttributes * class. FastR also uses different types to represent data/frame and factor which is @@ -1395,7 +1288,7 @@ public class RSerialize { public static final int ASCII_HEX = 2; public static final int BINARY = 3; - private static class Output extends Common { + private static final class Output extends Common { private State state; protected final POutputStream stream; @@ -2191,43 +2084,6 @@ 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.getOutputStream(), type, version, (CallHook) refhook); @@ -2522,4 +2378,135 @@ public class RSerialize { state.setCdr(state.closePairList()); return state.closePairList(); } + + /** + * A collection of static functions that will transform a pairlist into an AST using the + * {@link RCodeBuilder}. + */ + private static final class PairlistDeserializer { + + public static RFunction processFunction(Object car, Object cdr, Object tag, String functionName, String packageName) { + // car == arguments, cdr == body, tag == environment + + REnvironment environment = (REnvironment) tag; + MaterializedFrame enclosingFrame = environment.getFrame(); + RootCallTarget callTarget = RContext.getASTBuilder().rootFunction(RSyntaxNode.LAZY_DEPARSE, processArguments(car), processBody(cdr), functionName); + + FrameSlotChangeMonitor.initializeEnclosingFrame(callTarget.getRootNode().getFrameDescriptor(), enclosingFrame); + RFunction func = RDataFactory.createFunction(functionName, packageName, callTarget, null, enclosingFrame); + + RContext.getRRuntimeASTAccess().checkDebugRequest(func); + + /* + * TODO: this is missing the code that registers sources with RPackageSource! + */ + return func; + } + + public static RLanguage processLanguage(Object car, Object cdr, Object tag) { + return RDataFactory.createLanguage(processCall(car, cdr, tag).asRNode()); + } + + public static RPromise processPromise(Object car, Object cdr, Object tag) { + // car == value, cdr == expression, tag == environment + + Closure closure = Closure.create(processBody(cdr).asRNode()); + if (car == RUnboundValue.instance) { + REnvironment env = tag == RNull.instance ? REnvironment.baseEnv() : (REnvironment) tag; + return RDataFactory.createPromise(PromiseState.Explicit, closure, env.getFrame()); + } else { + return RDataFactory.createEvaluatedPromise(closure, car); + } + } + + private static RSyntaxNode process(Object value, boolean isCallLHS) { + if (value instanceof RSymbol) { + return RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, ((RSymbol) value).getName(), isCallLHS); + } else if (value instanceof RPairList) { + RPairList pl = (RPairList) value; + switch (pl.getType()) { + case LANGSXP: + return processCall(pl.car(), pl.cdr(), pl.getTag()); + case CLOSXP: + return processFunctionExpression(pl.car(), pl.cdr(), pl.getTag()); + default: + throw RInternalError.shouldNotReachHere("unexpected SXP type: " + pl.getType()); + } + } else { + assert !(value instanceof RMissing) : "should be handled outside"; + assert !(value instanceof RLanguage) : "unexpected RLanguage constant in unserialize"; + + return RContext.getASTBuilder().constant(RSyntaxNode.LAZY_DEPARSE, unwrapScalarValues(value)); + } + } + + /** Convert single-element atomic vectors to their primitive counterparts. */ + private static Object unwrapScalarValues(Object value) { + if (value instanceof RAbstractVector) { + RAbstractVector vector = (RAbstractVector) value; + if (vector.getLength() == 1 && (vector.getAttributes() == null || vector.getAttributes().isEmpty())) { + if (vector instanceof RAbstractDoubleVector || vector instanceof RAbstractIntVector || vector instanceof RAbstractStringVector || + vector instanceof RAbstractLogicalVector || vector instanceof RAbstractRawVector || vector instanceof RAbstractComplexVector) { + return vector.getDataAtAsObject(0); + } + } + } + return value; + } + + private static RSyntaxNode processCall(Object car, Object cdr, @SuppressWarnings("unused") Object tag) { + if (car instanceof RSymbol && ((RSymbol) car).getName().equals("function")) { + RPairList function = (RPairList) cdr; + return processFunctionExpression(function.car(), function.cdr(), function.getTag()); + } + return RContext.getASTBuilder().call(RSyntaxNode.LAZY_DEPARSE, process(car, true), processArguments(cdr)); + } + + private static RSyntaxNode processFunctionExpression(Object car, Object cdr, @SuppressWarnings("unused") Object tag) { + // car == arguments, cdr == body + return RContext.getASTBuilder().function(RSyntaxNode.LAZY_DEPARSE, processArguments(car), processBody(cdr), null); + } + + private static List<RCodeBuilder.Argument<RSyntaxNode>> processArguments(Object args) { + List<RCodeBuilder.Argument<RSyntaxNode>> list = new ArrayList<>(); + + RPairList arglist = args instanceof RNull ? null : (RPairList) args; + while (arglist != null) { + // for each argument: tag == name, car == value + String name = arglist.getTag() == RNull.instance ? null : ((RSymbol) arglist.getTag()).getName(); + RSyntaxNode value = arglist.car() == RMissing.instance ? null : process(arglist.car(), false); + list.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, name, value)); + arglist = next(arglist); + } + + return list; + } + + private static RPairList next(RPairList pairlist) { + if (pairlist.cdr() == RNull.instance) { + return null; + } else { + return (RPairList) pairlist.cdr(); + } + } + + private static RSyntaxNode processBody(Object cdr) { + if (cdr instanceof RPairList) { + RPairList pl = (RPairList) cdr; + switch (pl.getType()) { + case BCODESXP: + RAbstractListVector list = (RAbstractListVector) pl.cdr(); + return process(list.getDataAtAsObject(0), false); + case LISTSXP: + assert pl.cdr() == RNull.instance || (pl.cadr() == RNull.instance && pl.cddr() == RNull.instance); + return process(pl.car(), false); + case LANGSXP: + return processCall(pl.car(), pl.cdr(), pl.getTag()); + default: + throw RInternalError.shouldNotReachHere("unexpected SXP type in body: " + pl.getType()); + } + } + return process(cdr, false); + } + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RootWithBody.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RootWithBody.java new file mode 100644 index 0000000000000000000000000000000000000000..b2736e10e5e517f3d2d9d73c1109e44cfdfdd3ba --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RootWithBody.java @@ -0,0 +1,33 @@ +/* + * 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; + +import com.oracle.truffle.r.runtime.nodes.RNode; + +/** + * Used for testing. + */ +public interface RootWithBody { + + RNode getBody(); +} 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 330f46c849ec03ab2e440a41f1ca7cba95e70e8c..2e867d308647cce6bfdb76a499c4e95261cfeb45 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,8 +22,6 @@ */ package com.oracle.truffle.r.runtime.context; -import java.util.Map; - import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; @@ -119,11 +117,9 @@ public interface Engine { /** * Parse an R expression and return an {@link RExpression} object representing the Truffle ASTs - * for the components. The {Code constants} map can be used to replace some names in the source - * code with specific constants, which can be used to parse code that has no proper textual - * representation. + * for the components. */ - RExpression parse(Map<String, Object> constants, Source source) throws ParseException; + RExpression parse(Source source) throws ParseException; /** * This is the external interface from {@link PolyglotEngine#eval(Source)}. It is required to @@ -198,10 +194,4 @@ public interface Engine { * Essentially this is equivalent to {@link #evalFunction} using the {@code "print"} function. */ void printResult(Object value); - - /** - * This function a special fast path to create functions from code directly, without executing - * the intermediate "function" expression. - */ - RFunction parseFunction(Map<String, Object> constants, String name, Source source, MaterializedFrame enclosingFrame) throws ParseException; } 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 4530068e0a7e9e532dc892b7799500e9b2751c78..3ecd606d1a5dabd63307d6cc5a666185a29b4fcb 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 @@ -467,8 +467,8 @@ public final class RDataFactory { return traceDataCreated(new RPairList(car, cdr, tag, type)); } - public static RFunction createFunction(String name, RootCallTarget target, RBuiltinDescriptor builtin, MaterializedFrame enclosingFrame) { - return traceDataCreated(new RFunction(name, target, builtin, enclosingFrame)); + public static RFunction createFunction(String name, String packageName, RootCallTarget target, RBuiltinDescriptor builtin, MaterializedFrame enclosingFrame) { + return traceDataCreated(new RFunction(name, packageName, target, builtin, enclosingFrame)); } private static final AtomicInteger environmentCount = new AtomicInteger(); 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 8c434b5af633b287c8aed8345d2e8fe4b6625689..94d1d71fb49c3ac82b4b3f74a69a2f5fa3e18356 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 @@ -31,8 +31,6 @@ public class RExpression extends RListBase implements RAbstractVector { private static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Expression.getClazz()); - public String elementNamePrefix; - RExpression(Object[] data, int[] dims, RStringVector names) { super(data, dims, names); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java index 0ec52202d4806b9cf83be65955d91a1cdf35efd3..5dbc653ad82849d749f0803464e5527a3ec2be95 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java @@ -48,13 +48,15 @@ public final class RFunction extends RSharingAttributeStorage implements RTypedV public static final String NO_NAME = new String(""); - private String name; + private final String name; + private final String packageName; private final RootCallTarget target; private final RBuiltinDescriptor builtin; private final MaterializedFrame enclosingFrame; - RFunction(String name, RootCallTarget target, RBuiltinDescriptor builtin, MaterializedFrame enclosingFrame) { + RFunction(String name, String packageName, RootCallTarget target, RBuiltinDescriptor builtin, MaterializedFrame enclosingFrame) { + this.packageName = packageName; this.target = target; this.builtin = builtin; this.name = name; @@ -82,6 +84,10 @@ public final class RFunction extends RSharingAttributeStorage implements RTypedV return name; } + public String getPackageName() { + return packageName; + } + public RootCallTarget getTarget() { return target; } @@ -108,7 +114,7 @@ public final class RFunction extends RSharingAttributeStorage implements RTypedV @Override public RFunction copy() { - RFunction newFunction = RDataFactory.createFunction(getName(), getTarget(), getRBuiltin(), getEnclosingFrame()); + RFunction newFunction = RDataFactory.createFunction(getName(), getPackageName(), getTarget(), getRBuiltin(), getEnclosingFrame()); if (getAttributes() != null) { RAttributes newAttributes = newFunction.initAttributes(); for (RAttribute attr : getAttributes()) { @@ -119,5 +125,4 @@ public final class RFunction extends RSharingAttributeStorage implements RTypedV newFunction.setTypedValueInfo(getTypedValueInfo()); return newFunction; } - } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java index df4552dc03dcb5b2d10cb73346c3a01255848701..6b473ad2b615ed131f5eacece8e8fced1c4b0e5f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java @@ -26,6 +26,8 @@ import com.oracle.truffle.api.dsl.ImplicitCast; import com.oracle.truffle.api.dsl.TypeCast; import com.oracle.truffle.api.dsl.TypeCheck; import com.oracle.truffle.api.dsl.TypeSystem; +import com.oracle.truffle.api.dsl.internal.DSLOptions; +import com.oracle.truffle.api.dsl.internal.DSLOptions.DSLGenerator; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.r.runtime.RType; @@ -52,6 +54,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode; MaterializedFrame.class, FrameSlot.class, RAbstractIntVector.class, RAbstractDoubleVector.class, RAbstractLogicalVector.class, RAbstractComplexVector.class, RAbstractStringVector.class, RAbstractRawVector.class, RList.class, RAbstractVector.class, RSymbol.class, RPromise.class, RLanguage.class, RPairList.class, RExternalPtr.class, RS4Object.class, RAbstractContainer.class, RAttributable.class, RArgsValuesAndNames.class, RTypedValue.class, RType.class, Object[].class}) +@DSLOptions(defaultGenerator = DSLGenerator.DEFAULT) public class RTypes { @TypeCheck(RNull.class) diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/RPackageSource.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/RPackageSource.java deleted file mode 100644 index aa3e750c69c989a167bc13b163e3dde6b52d4b7c..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/RPackageSource.java +++ /dev/null @@ -1,283 +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.instrument; - -import java.io.BufferedWriter; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; - -import com.oracle.truffle.r.runtime.FastROptions; -import com.oracle.truffle.r.runtime.REnvVars; -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.Utils; -import com.oracle.truffle.r.runtime.data.RFunction; - -/** - * Support for locating the automatically generated source file for a package function when - * deserializing a lazily loaded function. FastR generates its AST from this deparsed source and so - * all instrumentation, including debugging, is tied to that source. This class manages the - * directory tree where these files are stored. An index that is based on a SHA1 digest of the - * source content is maintained allowing lookup when the function is loaded in subsequent - * executions. - * - * The {@code INDEX} file is a series of lines of the form: - * - * <pre> - * FNAME,FINGERPRINT,PKG,RPATH - * </pre> - * - * where FNAME is the function name as it appears in the source code and RPATH is a relative - * pathname to the generated source file from PKG. Internally we record the path in canonical form - * for fast processing. - */ -public class RPackageSource { - public static final String PKGSOURCE_PROJECT = "Rpkgsource"; - public static final String INDEX = "INDEX"; - private static final String SLASH_SWAP = "_slash_"; - private static final int FNAME = 0; - private static final int FINGERPRINT = 1; - private static final int PKG = 2; - private static final int RPATH = 3; - - private static class FunctionInfo { - /** - * name of function in source code. - */ - private final String sourceName; - private final String path; - private final String pkg; - - FunctionInfo(String sourceName, String pkg, String path) { - this.sourceName = sourceName; - this.pkg = pkg; - this.path = path; - } - } - - /** - * A map from source fingerprints to pathnames that are relative to the - * {@value #PKGSOURCE_PROJECT} directory. - */ - private static SortedMap<String, FunctionInfo> indexMap; - - /** - * A reverse map from pathnames to function names. - */ - private static Map<String, String> pathToNameMap; - - public static void initialize() { - if (FastROptions.LoadPkgSourcesIndex.getBooleanValue()) { - Path indexPath = indexPath(); - try { - List<String> lines = Files.readAllLines(indexPath); - checkCreateMaps(); - Path dirPath = dirPath(); - for (String line : lines) { - String[] parts = line.split(","); - String canonPath = dirPath.resolve(parts[PKG]).resolve(parts[RPATH]).toString(); - indexMap.put(parts[FINGERPRINT], new FunctionInfo(parts[FINGERPRINT], parts[PKG], canonPath)); - pathToNameMap.put(canonPath, parts[FNAME]); - } - } catch (IOException ex) { - // no index, not a problem - } - } - } - - private static void checkCreateMaps() { - if (indexMap == null) { - indexMap = new TreeMap<>(); - pathToNameMap = new HashMap<>(); - } - } - - /** - * Lookup the given source fingerprint in the index and return a canonical path for the - * associated file or {@code null} if not found. - */ - public static String lookup(String source) { - if (indexMap == null) { - return null; - } - String fingerprint = getFingerPrint(source.getBytes()); - FunctionInfo info = indexMap.get(fingerprint); - if (info == null) { - return null; - } else { - return info.path; - } - } - - private static void register(String fname, String pkg, Path sourcePath) { - try { - byte[] sourceData = Files.readAllBytes(sourcePath); - String fingerprint = getFingerPrint(sourceData); - FunctionInfo prev = indexMap.get(fingerprint); - if (!((prev == null) || (prev.sourceName == fname && prev.path == sourcePath.toString()))) { - /* - * This could arise in several ways. Most likely the same function is assigned to - * multiple names in the same package, or the same (likely trivial) body is assigned - * to several unrelated functions. These are annoying but essentially benign. - */ - RError.warning(RError.SHOW_CALLER2, RError.Message.GENERIC, "two package functions with same fingerprint, prev: '" + qualName(prev.pkg, prev.sourceName) + "', this '" + - qualName(pkg, fname) + "'"); - return; - } - indexMap.put(fingerprint, new FunctionInfo(fname, pkg, dirPath().resolve(pkg).relativize(sourcePath).toString())); - } catch (IOException ex) { - throw RInternalError.shouldNotReachHere(ex.getMessage()); - } - } - - private static String getFingerPrint(byte[] sourceData) { - try { - MessageDigest digest = MessageDigest.getInstance("SHA1"); - return Utils.toHexString(digest.digest(sourceData)); - } catch (NoSuchAlgorithmException ex) { - throw RInternalError.shouldNotReachHere(ex.getMessage()); - } - } - - /** - * Temporary save of the results from {@link #deparsed}. - */ - private static String deparseResult; - private static boolean deparseError; - - /** - * Called from {@link RSerialize} with the deparsed content of a unserialized closure - * (function). - * - * @param deparse deparse closure - * @param isError {@code true} iff the parse of {@code deparse} failed. - */ - public static void deparsed(String deparse, boolean isError) { - deparseResult = deparse; - deparseError = isError; - } - - /** - * Called just prior to the (expected) unserialization of the closure associated with - * {@code fname}. - */ - @SuppressWarnings("unused") - public static void preLoad(String pkg, String fname) { - // Cause RSerialize to call "deparsed". - RSerialize.setSaveDeparse(true); - checkCreateMaps(); - deparseResult = null; - deparseError = false; - } - - /** - * Called after the unserialization has occurred to bind {@code fname} to the resulting closure. - */ - public static void postLoad(String pkg, String fname, Object val) { - RSerialize.setSaveDeparse(false); - if (val instanceof RFunction) { - String qualName = qualName(pkg, fname); - if (deparseResult != null) { - if (deparseError) { - RError.warning(RError.SHOW_CALLER2, RError.Message.GENERIC, "the function '" + qualName + "' did not deparse successfully"); - // write the file anyway - } - try { - Path target = targetPath(pkg, fname); - try (FileWriter wr = new FileWriter(target.toFile())) { - wr.write(deparseResult); - } - register(fname, pkg, target); - } catch (IOException ex) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, ex.getMessage()); - } - } else { - RError.warning(RError.SHOW_CALLER2, RError.Message.GENERIC, "the function '" + qualName + "' has already been unserialized"); - } - } - } - - private static String qualName(String pkg, String fname) { - return pkg + "::" + fname; - } - - public static String decodeName(String path) { - String name = pathToNameMap.get(path); - RInternalError.guarantee(name != null); - return name; - } - - /** - * Some function names do not map into useful or even legal filenames. This method takes care of - * that. - */ - private static String mungeName(String fname) { - String result = fname; - result = result.replace("/", SLASH_SWAP); - return result; - } - - private static Path targetPath(String pkg, String fnameArg) throws IOException { - Path targetDir = dirPath().resolve(pkg); - Files.createDirectories(targetDir); - String fname = mungeName(fnameArg); - Path target = targetDir.resolve(fname + ".R"); - return target; - } - - public static void saveMap() { - try (BufferedWriter wr = new BufferedWriter(new FileWriter(indexPath().toFile()))) { - for (Map.Entry<String, FunctionInfo> entry : indexMap.entrySet()) { - wr.append(entry.getValue().sourceName); - wr.append(','); - wr.append(entry.getKey()); - wr.append(','); - wr.append(entry.getValue().pkg); - wr.append(','); - wr.append(entry.getValue().path); - wr.append('\n'); - } - } catch (IOException ex) { - Utils.rSuicide("error writing package source index"); - } - } - - private static Path dirPath() { - return FileSystems.getDefault().getPath(REnvVars.rHome(), PKGSOURCE_PROJECT); - } - - private static Path indexPath() { - return dirPath().resolve(INDEX); - } -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxElement.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxElement.java index 685eb5f0975e71f2cf5aa99f82dcee122977c009..a97299f2bab84533cbd3f1f3db9979a277c99df5 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxElement.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxElement.java @@ -37,7 +37,7 @@ public interface RSyntaxElement { /** * This is a special version of {@link #getSourceSection} that does not try to - * {@link RDeparse#ensureSourceSection(RSyntaxElement) deparse} {@link SourceSection}s that are + * {@link RDeparse#ensureSourceSection(RSyntaxNode) deparse} {@link SourceSection}s that are * {@link RSyntaxNode#INTERNAL internal}. */ SourceSection getLazySourceSection(); 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 feeb6a124fda2e5480f08e804be6b2e37778fb5a..6b2bbd3a2e5236671455d283ddb47f379af0254d 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 @@ -350,9 +350,9 @@ public final class NACheck { } result[i] = intValue; } - if (warning) { - RError.warning(RError.SHOW_CALLER2, RError.Message.NA_INTRODUCED_COERCION); - } + } + if (warning) { + RError.warning(RError.SHOW_CALLER2, RError.Message.NA_INTRODUCED_COERCION_INT); } return result; } 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 9af4df8ade2df0f8e35a45229f529560b1807124..2dc0adb4f7917a46ba4d152b67be4546abfc9742 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 @@ -4039,7 +4039,7 @@ attr(,"match.length") [1] -1 -##com.oracle.truffle.r.test.builtins.TestBuiltin_args.testArgs# +##com.oracle.truffle.r.test.builtins.TestBuiltin_args.testArgs#Output.IgnoreWhitespace# #{ f <- function(x=1, y) x + y; args(f); } function (x = 1, y) NULL @@ -6139,12 +6139,12 @@ Error in as.vector(x, "expression") : #argv <- structure(list(x = 1), .Names = 'x');do.call('as.expression', argv) expression(1) -##com.oracle.truffle.r.test.builtins.TestBuiltin_asfunction.testasfunction# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asfunction.testasfunction#Output.IgnoreWhitespace# #as.function(c(alist(a=1+14, b=foo(x),c=), quote(a+foo(c)*b))) function (a = 1 + 14, b = foo(x), c) a + foo(c) * b -##com.oracle.truffle.r.test.builtins.TestBuiltin_asfunction.testasfunction# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asfunction.testasfunction#Output.IgnoreWhitespace# #f <- function() a+foo(c)*b; as.function(c(alist(a=1+14, b=foo(x),c=), body(f))) function (a = 1 + 14, b = foo(x), c) a + foo(c) * b @@ -6438,7 +6438,7 @@ integer(0) #argv <- list(4999.0000000001);as.integer(argv[[1]]); [1] 4999 -##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testasinteger17#Ignored.Unknown#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testasinteger17# #argv <- list(structure(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', ' NA')));as.integer(argv[[1]]); [1] 100 0 NA NA NA 3 NA Warning message: @@ -9540,7 +9540,7 @@ In bitwShiftL(c(1, 2, 3, 4), c("a")) : NAs introduced by coercion #{ bitwShiftL(c(25,57,66), c(10,20,30,40,50,60)) } [1] 25600 59768832 NA NA NA NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions# #{ bitwShiftL(c(3+3i), c(3,2,4)) } Error in bitwShiftL(c(3 + (0+3i)), c(3, 2, 4)) : unimplemented type 'complex' in 'bitShiftL' @@ -15844,11 +15844,11 @@ Error in print(x, y) : #deparse(quote(cat(-17))) [1] "cat(-17)" -##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse#Ignored.OutputFormatting# +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse# #deparse(quote(cat(-199.1234-5i))) [1] "cat(-199.1234 - (0+5i))" -##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse#Ignored.OutputFormatting# +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse# #deparse(quote(cat(-5i))) [1] "cat(-(0+5i))" @@ -15920,7 +15920,7 @@ Error in print(x, y) : #deparse(quote(cat(17))) [1] "cat(17)" -##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse#Ignored.OutputFormatting# +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse# #deparse(quote(cat(199.1234-5i))) [1] "cat(199.1234 - (0+5i))" @@ -17227,7 +17227,7 @@ $foo #{ digamma(1) } [1] -0.5772157 -##com.oracle.truffle.r.test.builtins.TestBuiltin_digamma.testDiGamma#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_digamma.testDiGamma# #{ digamma(1+1i) } Error in digamma(1 + (0+1i)) : unimplemented complex function @@ -17444,7 +17444,7 @@ Error in dim(x) <- integer() : length-0 dimension vector is invalid #{ x<-1:12; dim(x)<-c(12); x } [1] 1 2 3 4 5 6 7 8 9 10 11 12 -##com.oracle.truffle.r.test.builtins.TestBuiltin_dim.testDimensions#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_dim.testDimensions# #{ x<-1:12; dim(x)<-c(12+10i); x } [1] 1 2 3 4 5 6 7 8 9 10 11 12 Warning message: @@ -27244,7 +27244,7 @@ Levels: age1824 age2534 age3544 age4554 age5564 age6599 #{ lgamma(1) } [1] 0 -##com.oracle.truffle.r.test.builtins.TestBuiltin_lgamma.testLgamma#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_lgamma.testLgamma# #{ lgamma(1+1i) } Error in lgamma(1 + (0+1i)) : unimplemented complex function @@ -30949,7 +30949,7 @@ In max() : no non-missing arguments to max; returning -Inf #{ max(2L, 4L) } [1] 4 -##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum# #{ max(42+42i, 7+7i) } Error in max(42 + (0+42i), 7 + (0+7i)) : invalid 'type' (complex) of argument @@ -31644,7 +31644,7 @@ In min() : no non-missing arguments to min; returning Inf #{ min(2L, 4L) } [1] 2 -##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum# #{ min(42+42i, 7+7i) } Error in min(42 + (0+42i), 7 + (0+7i)) : invalid 'type' (complex) of argument @@ -45717,7 +45717,7 @@ Error in signif(42.1234, "2") : #{ signif(42.1234, 1:2) } [1] 40 42 -##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif#Output.IgnoreErrorContext# +##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 @@ -53853,10 +53853,263 @@ Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 [1] 123 [1] 123 -##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testserializeAndUnserializeClosure#Ignored.OutputFormatting# +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testserializeAndUnserializeClosure#Output.IgnoreWhitespace# #unserialize(serialize(function (x) { x }, NULL)) function (x) { x } +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote("bar"), connection=NULL)) +[1] "bar" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote('asdf'), connection=NULL)) +[1] "asdf" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote('baz'), connection=NULL)) +[1] "baz" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote((a %asdf% b)), connection=NULL)) +(a %asdf% b) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote((a+b)), connection=NULL)) +(a + b) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(111+11), connection=NULL)) +111 + 11 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(111+8i), connection=NULL)) +111 + (0+8i) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(111L), connection=NULL)) +[1] 111 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(FALSE), connection=NULL)) +[1] FALSE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(NA_character_ + NA_complex_ + NA_integer_ + NA_real_), connection=NULL)) +NA_character_ + (NA_complex_) + NA_integer_ + NA_real_ + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(NA_character_), connection=NULL)) +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(NA_complex_), connection=NULL)) +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(NA_integer_), connection=NULL)) +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(NA_real_), connection=NULL)) +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(TRUE), connection=NULL)) +[1] TRUE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.IgnoreWhitespace# +#options(keep.source=FALSE); unserialize(serialize(quote(a(b(c(d(function (e, ...) { f(g)$h.i}))))), connection=NULL)) +a(b(c(d(function(e, ...) { + f(g)$h.i +})))) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(a+b), connection=NULL)) +a + b + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(f(g)$h.i), connection=NULL)) +f(g)$h.i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(foo(a,b,c)), connection=NULL)) +foo(a, b, c) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.IgnoreWhitespace# +#options(keep.source=FALSE); unserialize(serialize(quote(function() new("foo", x)), connection=NULL)) +function() new("foo", x) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(function(x) { `+`(`(`("BAR"), x) }), connection=NULL)) +function(x) { + ("BAR") + x +} + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.IgnoreWhitespace# +#options(keep.source=FALSE); unserialize(serialize(quote(function(x) { new("BAR", x) }), connection=NULL)) +function(x) { + new("BAR", x) +} + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.IgnoreWhitespace# +#options(keep.source=FALSE); unserialize(serialize(quote(function(x, ...) { new("BAR", x) }), connection=NULL)) +function(x, ...) { + new("BAR", x) +} + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.IgnoreWhitespace# +#options(keep.source=FALSE); unserialize(serialize(quote(function(x,y) { TRUE }), connection=NULL)) +function(x, y) { + TRUE +} + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.IgnoreWhitespace# +#options(keep.source=FALSE); unserialize(serialize(quote(function(x,y) { new("BAR", x) }), connection=NULL)) +function(x, y) { + new("BAR", x) +} + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.IgnoreWhitespace# +#options(keep.source=FALSE); unserialize(serialize(quote(function(x,y,...) { 1 }), connection=NULL)) +function(x, y, ...) { + 1 +} + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.IgnoreWhitespace# +#options(keep.source=FALSE); unserialize(serialize(quote(function(x,y=1,...) { NA }), connection=NULL)) +function(x, y = 1, ...) { + NA +} + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Ignored.OutputFormatting# +#options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { !!NA }), connection=NULL)) +function(x = { + 1 + a +}, y, ...) { + !(!NA) +} + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { !1+5i }), connection=NULL)) +function(x = { + 1 + a +}, y, ...) { + !1 + (0+5i) +} + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { NA }), connection=NULL)) +function(x = { + 1 + a +}, y, ...) { + NA +} + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y=c(1,2,3),z="foo",...) { !1+5i }), connection=NULL)) +function(x = { + 1 + a +}, y = c(1, 2, 3), z = "foo", ...) { + !1 + (0+5i) +} + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(if (a * 2 < 199) b + foo(x,y,foo=z+1,bar=)), connection=NULL)) +if (a * 2 < 199) b + foo(x, y, foo = z + 1, bar = ) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(if (a) b else c), connection=NULL)) +if (a) b else c + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(if (a) {b} else {c}), connection=NULL)) +if (a) { + b +} else { + c +} + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(if ({a}) {b} else {c}), connection=NULL)) +if ({ + a +}) { + b +} else { + c +} + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.IgnoreWhitespace# +#options(keep.source=FALSE); unserialize(serialize(quote(repeat {b; if (c) next else break}), connection=NULL)) +repeat { + b + if (c) + next + else break +} + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(while (a) b), connection=NULL)) +while (a) b + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote(x), connection=NULL)) +x + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); unserialize(serialize(quote({ foo(a,b,c) }), connection=NULL)) +{ + foo(a, b, c) +} + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#options(keep.source=FALSE); val <- defaultPrototype(); unserialize(serialize(val, connection=NULL)) +<S4 Type Object> + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.ContainsReferences# +#options(keep.source=FALSE); val <- list(enclos = new.env(hash=FALSE)); unserialize(serialize(val, connection=NULL)) +$enclos +<environment: 0x7fa93ab11ab0> + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.ContainsReferences# +#options(keep.source=FALSE); val <- new.env(hash=FALSE); unserialize(serialize(val, connection=NULL)) +<environment: 0x7fc0c88c78a8> + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.ContainsReferences# +#options(keep.source=FALSE); val <- new.env(hash=FALSE); val$a <- 'foo'; unserialize(serialize(val, connection=NULL)) +<environment: 0x7fc5914a1ad8> + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.ContainsReferences# +#options(keep.source=FALSE); val <- new.env(hash=FALSE); val$b <- 123; unserialize(serialize(val, connection=NULL)) +<environment: 0x7fe9532eb830> + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.ContainsReferences# +#options(keep.source=FALSE); val <- new.env(hash=FALSE); val$c <- 1233L; unserialize(serialize(val, connection=NULL)) +<environment: 0x7ff64a5862d8> + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.ContainsReferences# +#options(keep.source=FALSE); val <- new.env(hash=FALSE); val$d <- TRUE; unserialize(serialize(val, connection=NULL)) +<environment: 0x7fcac6388ad8> + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.ContainsReferences# +#options(keep.source=FALSE); val <- new.env(hash=FALSE); val$e <- 5+9i; unserialize(serialize(val, connection=NULL)) +<environment: 0x7f80c3679d50> + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Output.ContainsReferences# +#options(keep.source=FALSE); val <- new.env(hash=FALSE); val$f <- NA; unserialize(serialize(val, connection=NULL)) +<environment: 0x7fa9028d50d8> + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# +#setClass('foo', slots = c(x='numeric', y='numeric')); t1 <- new('foo', x=4, y=c(77,88)); options(keep.source=FALSE); unserialize(serialize(t1, connection=NULL)) +An object of class "foo" +Slot "x": +[1] 4 + +Slot "y": +[1] 77 88 + + ##com.oracle.truffle.r.test.builtins.TestBuiltin_utf8ToInt.testutf8ToInt1#Ignored.Unknown# #argv <- list('lasy'); .Internal(utf8ToInt(argv[[1]])) [1] 108 97 115 121 @@ -67789,7 +68042,7 @@ NULL #{ (0-5):(0-9) } [1] -5 -6 -7 -8 -9 -##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction# #{ (1:3):(1:3) } [1] 1 Warning messages: @@ -67798,7 +68051,7 @@ Warning messages: 2: In (1:3):(1:3) : numerical expression has 3 elements: only the first used -##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction# #{ (1:3):3 } [1] 1 2 3 Warning message: @@ -99435,23 +99688,23 @@ Error in x[[1 + (0+1i), 1]] <- c(7, 42) : #{ x<-c(1,2,3,4); dim(x)<-c(2,2); x[[1+1i, 1]]<-integer() } Error in x[[1 + (0+1i), 1]] <- integer() : replacement has length zero -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-c(1,2,3,4); x[1+1i]<-NULL } Error in x[1 + (0+1i)] <- NULL : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-c(1,2,3,4); x[1+1i]<-c(1) } Error in x[1 + (0+1i)] <- c(1) : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-c(1,2,3,4); x[1+1i]<-c(1,2) } Error in x[1 + (0+1i)] <- c(1, 2) : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-c(1,2,3,4); x[1+1i]<-c(1,2,3) } Error in x[1 + (0+1i)] <- c(1, 2, 3) : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-c(1,2,3,4); x[1+1i]<-integer() } Error in x[1 + (0+1i)] <- integer() : invalid subscript type 'complex' @@ -99460,7 +99713,7 @@ Error in x[1 + (0+1i)] <- integer() : invalid subscript type 'complex' Error in x[[1 + (0+1i)]] <- NULL : more elements supplied than there are to replace -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-c(1,2,3,4); x[[1+1i]]<-c(1) } Error in x[[1 + (0+1i)]] <- c(1) : invalid subscript type 'complex' @@ -99518,43 +99771,43 @@ Error in `[[<-`(`*tmp*`, 1 + (0+1i), 1, value = c(7, 42)) : Error in `[[<-`(`*tmp*`, 1 + (0+1i), 1, value = integer(0)) : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-list(1,2,3,4); x[1+1i]<-NULL } Error in x[1 + (0+1i)] <- NULL : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-list(1,2,3,4); x[1+1i]<-c(1) } Error in x[1 + (0+1i)] <- c(1) : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-list(1,2,3,4); x[1+1i]<-c(1,2) } Error in x[1 + (0+1i)] <- c(1, 2) : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-list(1,2,3,4); x[1+1i]<-c(1,2,3) } Error in x[1 + (0+1i)] <- c(1, 2, 3) : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-list(1,2,3,4); x[1+1i]<-integer() } Error in x[1 + (0+1i)] <- integer() : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-list(1,2,3,4); x[[1+1i]]<-NULL } Error in x[[1 + (0+1i)]] <- NULL : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-list(1,2,3,4); x[[1+1i]]<-c(1) } Error in x[[1 + (0+1i)]] <- c(1) : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-list(1,2,3,4); x[[1+1i]]<-c(1,2) } Error in x[[1 + (0+1i)]] <- c(1, 2) : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-list(1,2,3,4); x[[1+1i]]<-c(1,2,3) } Error in x[[1 + (0+1i)]] <- c(1, 2, 3) : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testComplexIndex# #{ x<-list(1,2,3,4); x[[1+1i]]<-integer() } Error in x[[1 + (0+1i)]] <- integer() : invalid subscript type 'complex' @@ -102906,7 +103159,7 @@ Error in x[[NA]] <- NULL : #{ x<-1:2; dim(x)<-c(1,2); u<-2+2i; x[[u, u]] } Error in x[[u, u]] : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:2; dim(x)<-c(1,2); x[2+2i, 2+2i] } Error in x[2 + (0+2i), 2 + (0+2i)] : invalid subscript type 'complex' @@ -103103,7 +103356,7 @@ Error in `[[<-`(`*tmp*`, c(0, 1, 1), value = c(42, 43)) : Error in x[[c(0, 42 + (0+7i))]] <- c(42, 43) : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:4; dim(x)<-c(2,2); x[[c(1+1i)]]<-c(42); x } Error in x[[c(1 + (0+1i))]] <- c(42) : invalid subscript type 'complex' @@ -103262,16 +103515,16 @@ In x[c(0, 1)] <- c(42, 43) : [1,] 43 3 [2,] 2 4 -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:4; dim(x)<-c(2,2); x[c(0,42+7i)]<-c(42,43); x } Error in x[c(0, 42 + (0+7i))] <- c(42, 43) : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:4; dim(x)<-c(2,2); x[c(1+1i)]<-c(42); x } Error in x[c(1 + (0+1i))] <- c(42) : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:4; dim(x)<-c(2,2); x[c(1+1i)]<-c(42,43); x } Error in x[c(1 + (0+1i))] <- c(42, 43) : invalid subscript type 'complex' @@ -103279,7 +103532,7 @@ Error in x[c(1 + (0+1i))] <- c(42, 43) : invalid subscript type 'complex' #{ x<-1:4; dim(x)<-c(2,2); x[c(1+1i)]<-integer(); x } Error in x[c(1 + (0+1i))] <- integer() : invalid subscript type 'complex' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:4; dim(x)<-c(2,2); x[c(1+1i,42+7i,3+3i)]<-c(42,43); x } Error in x[c(1 + (0+1i), 42 + (0+7i), 3 + (0+3i))] <- c(42, 43) : invalid subscript type 'complex' @@ -108502,7 +108755,7 @@ Error in x[[list(-0, -1)]] : #{ x <- 1:2; x[[list(0)]] } Error in x[[list(0)]] : invalid subscript type 'list' -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorIndex# #{ x <- 1:3; x[function(){3}] } Error in x[function() { : invalid subscript type 'closure' @@ -108667,7 +108920,7 @@ Error in x[[i]] : invalid subscript type 'complex' #{ x <- list(a=1,b=1:3) ; f <- function(i) { x[[i]] } ; f(c(2,2)) ; x <- f ; f(2+3i) } Error in x[[i]] : object of type 'closure' is not subsettable -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorIndex#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorIndex# #{ x <- list(a=1,b=1:3) ; x[[2+3i]] } Error in x[[2 + (0+3i)]] : invalid subscript type 'complex' @@ -108997,7 +109250,7 @@ Error in b[c(3, 2)] <- 2 : [1] 2 -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ b <- as.raw(1:5) ; b[c(TRUE,FALSE,TRUE)] <- c(1+2i,3+4i) ; b } Error in b[c(TRUE, FALSE, TRUE)] <- c(1 + (0+2i), 3 + (0+4i)) : incompatible types (from complex to raw) in subassignment type fix @@ -109115,7 +109368,7 @@ Error in b[c(TRUE, FALSE, FALSE)] <- NULL : replacement has length zero [1] 1+2i -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ b <- c(1,2,5) ; b[c(TRUE,NA,TRUE)] <- list(TRUE,1+2i) ; b } Error in b[c(TRUE, NA, TRUE)] <- list(TRUE, 1 + (0+2i)) : NAs are not allowed in subscripted assignments @@ -110685,6 +110938,102 @@ Error: 'x' is NULL #.Call(stats:::C_cov, c('1','2','3','4','5'), 1:5, 4, FALSE) [1] 2.5 +##com.oracle.truffle.r.test.library.stats.TestExternal_qgamma.testQgamma# +#qgamma(0, 1) +[1] 0 + +##com.oracle.truffle.r.test.library.stats.TestExternal_qgamma.testQgamma# +#qgamma(0.1, 1) +[1] 0.1053605 + +##com.oracle.truffle.r.test.library.stats.TestExternal_qgamma.testQgamma# +#qgamma(0.1, 10, rate=2, lower.tail=FALSE) +[1] 7.102995 + +##com.oracle.truffle.r.test.library.stats.TestExternal_qgamma.testQgamma# +#qgamma(1, 1) +[1] Inf + +##com.oracle.truffle.r.test.library.stats.TestExternal_qgamma.testQgamma# +#qgamma(c(0.1, 0.5, 0.99), c(10, 20), 7) +[1] 0.8887578 2.8096675 2.6833025 + +##com.oracle.truffle.r.test.library.stats.TestExternal_qgamma.testQgamma# +#qgamma(log(1.2e-8), 10, log.p=TRUE) +[1] 0.7848489 + +##com.oracle.truffle.r.test.library.stats.TestExternal_qgamma.testQgammaWrongArgs# +#qgamma(10, 1) +[1] NaN +Warning message: +In qgamma(10, 1) : NaNs produced + +##com.oracle.truffle.r.test.library.stats.TestExternal_rbinom.testRbinom# +#set.seed(42); rbinom('10', 10, 0.5) + [1] 7 7 4 7 6 5 6 3 6 6 + +##com.oracle.truffle.r.test.library.stats.TestExternal_rbinom.testRbinom#Output.IgnoreWarningContext# +#set.seed(42); rbinom('aa', 10, 0.5) +Error in rbinom("aa", 10, 0.5) : invalid arguments +In addition: Warning message: +In rbinom("aa", 10, 0.5) : NAs introduced by coercion + +##com.oracle.truffle.r.test.library.stats.TestExternal_rbinom.testRbinom# +#set.seed(42); rbinom(10, 10, 0.5) + [1] 7 7 4 7 6 5 6 3 6 6 + +##com.oracle.truffle.r.test.library.stats.TestExternal_rbinom.testRbinom# +#set.seed(42); rbinom(10, 2:10, c(0.1, 0.5, 0.9)) + [1] 1 3 4 1 3 6 1 3 9 0 + +##com.oracle.truffle.r.test.library.stats.TestExternal_rbinom.testRbinom# +#set.seed(42); rbinom(1:10, 2:10, c(0.1, 0.5, 0.9)) + [1] 1 3 4 1 3 6 1 3 9 0 + +##com.oracle.truffle.r.test.library.stats.TestExternal_rbinom.testRbinom# +#set.seed(42); rbinom(c(1,2), 11:12, c(0.1, 0.5, 0.9)) +[1] 3 9 + +##com.oracle.truffle.r.test.library.stats.TestExternal_rnorm.testRnorm# +#set.seed(42); rnorm('10', 10, 5) + [1] 16.854792 7.176509 11.815642 13.164313 12.021342 9.469377 17.557610 + [8] 9.526705 20.092119 9.686430 + +##com.oracle.truffle.r.test.library.stats.TestExternal_rnorm.testRnorm#Output.IgnoreWarningContext# +#set.seed(42); rnorm('aa', 10, 0.5) +Error in rnorm("aa", 10, 0.5) : invalid arguments +In addition: Warning message: +In rnorm("aa", 10, 0.5) : NAs introduced by coercion + +##com.oracle.truffle.r.test.library.stats.TestExternal_rnorm.testRnorm# +#set.seed(42); rnorm(10, 10, 10) + [1] 23.709584 4.353018 13.631284 16.328626 14.042683 8.938755 25.115220 + [8] 9.053410 30.184237 9.372859 + +##com.oracle.truffle.r.test.library.stats.TestExternal_rnorm.testRnorm# +#set.seed(42); rnorm(10, 2:10, c(0.1, 0.5, 0.9)) + [1] 2.137096 2.717651 4.326816 5.063286 6.202134 6.904488 8.151152 + [8] 8.952670 11.816581 1.993729 + +##com.oracle.truffle.r.test.library.stats.TestExternal_rnorm.testRnorm# +#set.seed(42); rnorm(1:10, 2:10, c(0.1, 0.5, 0.9)) + [1] 2.137096 2.717651 4.326816 5.063286 6.202134 6.904488 8.151152 + [8] 8.952670 11.816581 1.993729 + +##com.oracle.truffle.r.test.library.stats.TestExternal_rnorm.testRnorm# +#set.seed(42); rnorm(c(1,2), 11:12, c(0.1, 0.5, 0.9)) +[1] 11.13710 11.71765 + +##com.oracle.truffle.r.test.library.stats.TestExternal_runif.testRunif# +#set.seed(1); runif(5); +[1] 0.2655087 0.3721239 0.5728534 0.9082078 0.2016819 + +##com.oracle.truffle.r.test.library.stats.TestExternal_runif.testRunif# +#set.seed(1); runif(5, 10, 2.5); +[1] NaN NaN NaN NaN NaN +Warning message: +In runif(5, 10, 2.5) : NAs produced + ##com.oracle.truffle.r.test.library.stats.TestFitting.testLm#Output.IgnoreWhitespace# #y <- c(26.55, 37.21, 57.28, 90.82, 20.16, 89.838, 94.46, 20.5, 17.6, 68.7, 38.41, 76.9, 49.7, 71, 99.19, 16); x <- c(26.55, 37.21, 57.28, 90.82, 20.16, 89.838, 94.46, 20.5, 17.6, 68.7, 38.41, 76.9, 49.7, 71, 99.19, 16); res <- lm(y~x); print(res$coefficients);print(res$fitted.values);print(res$xlevels);print(res$residuals);print(res$assign);print(res$effects);print(res$qr$qr);print(res$rank);print(res$model); (Intercept) x diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_args.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_args.java index ede905ba639f426d618613cca8cc3c0713dbd661..1303d70f84ad911190805a46d15c50e00067ebc2 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_args.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_args.java @@ -47,6 +47,6 @@ public class TestBuiltin_args extends TestBase { assertEval("{ f <- function(a) {}; fa <- args(f); }"); assertEval("{ f <- function(a, b) {}; fa <- args(f); }"); assertEval("{ sa <- args(sum); }"); - assertEval("{ f <- function(x=1, y) x + y; args(f); }"); + assertEval(Output.IgnoreWhitespace, "{ f <- function(x=1, y) x + y; args(f); }"); } } 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 b0432a40b7d1b1a86be53c5f91686a31760b0bb6..95b6ce40cdbe5442990d31fa483f141e632c6951 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 @@ -30,8 +30,8 @@ public class TestBuiltin_asfunction extends TestBase { @Test public void testasfunction() { - assertEval("as.function(c(alist(a=1+14, b=foo(x),c=), quote(a+foo(c)*b)))"); - assertEval("f <- function() a+foo(c)*b; as.function(c(alist(a=1+14, b=foo(x),c=), body(f)))"); + assertEval(Output.IgnoreWhitespace, "as.function(c(alist(a=1+14, b=foo(x),c=), quote(a+foo(c)*b)))"); + assertEval(Output.IgnoreWhitespace, "f <- function() a+foo(c)*b; as.function(c(alist(a=1+14, b=foo(x),c=), body(f)))"); assertEval("foo <- function(x) x*2; as.function(c(alist(a=1+14, b=foo(x),c=), quote(a+foo(c)*b)))(c=3,b=1)"); assertEval("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)"); assertEval("{ as.function(alist(42))() }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java index 90ef68d16f5f7d62ed031dd2d04b0ac51a669b21..dc6b2ebb7ac90798f560f21007f87cbc3592583f 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java @@ -96,8 +96,7 @@ public class TestBuiltin_asinteger extends TestBase { @Test public void testasinteger17() { - assertEval(Ignored.Unknown, Output.IgnoreWarningContext, - "argv <- list(structure(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', ' NA')));as.integer(argv[[1]]);"); + assertEval("argv <- list(structure(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', ' NA')));as.integer(argv[[1]]);"); } @Test 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 6e33441b3be4ea000c0c32de930a6a988bd4e62e..480abb29840f7e8e24970ebbfd98e7724e7fcb35 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 @@ -31,8 +31,7 @@ public class TestBuiltin_bitwiseShiftL extends TestBase { assertEval("{ bitwShiftL(TRUE, c(TRUE, FALSE)) }"); - // Error message mismatch - assertEval(Output.IgnoreErrorContext, "{ bitwShiftL(c(3+3i), c(3,2,4)) }"); + assertEval("{ bitwShiftL(c(3+3i), c(3,2,4)) }"); // Warning message mismatch assertEval(Output.IgnoreWarningContext, "{ bitwShiftL(c(3,2,4), c(3+3i)) }"); // No warning message printed for NAs produced by coercion 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 f1581fdeebbebcd9780417bd66467ff65e4c88be..071f3a353962ee7d1205b4a095f5ffb4358ca974 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 @@ -270,7 +270,7 @@ public class TestBuiltin_deparse extends TestBase { assertEval("argv <- list(quote(x[[i]] <- 0.9999997), 500L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } - private static final String[] VALUES = new String[]{"TRUE", "c(T, F)", "17", "-17", "0L", "-0L", "16L", "-16L", "5i", "NA_integer_", "NA_complex_", + private static final String[] VALUES = new String[]{"TRUE", "c(T, F)", "17", "-17", "0L", "-0L", "16L", "-16L", "5i", "-5i", "199.1234-5i", "-199.1234-5i", "NA_integer_", "NA_complex_", "NA_real_", "NA_character_", "1:2", "1:6", "0", "1", "1000", "10000", "99999", "100000000", "10000000000000", "0.1", "0.123", "0.00123", "0.0000000001", "0.0000000000000001", "1.545234523452345252523452345", "Inf", "NaN", "-0", "-1", "-1000", "-10000", "-99999", "-100000000", "-10000000000000", "-0.1", "-0.123", "-0.00123", "-0.0000000001", "-0.0000000000000001", "-1.545234523452345252523452345", "-Inf", "c(1L,2L,3L)", "c(1,2,3)", "c(NA_integer_, 1L,2L,3L)", "c(1L,2L,3L, NA_integer_)", "c(3L,2L,1L)", @@ -280,12 +280,6 @@ public class TestBuiltin_deparse extends TestBase { public void testDeparse() { assertEval(template("deparse(%0)", VALUES)); assertEval(template("deparse(quote(cat(%0)))", VALUES)); - assertEval("deparse(-5i)"); - assertEval(Ignored.OutputFormatting, "deparse(quote(cat(-5i)))"); - assertEval("deparse(199.1234-5i)"); - assertEval(Ignored.OutputFormatting, "deparse(quote(cat(199.1234-5i)))"); - assertEval("deparse(-199.1234-5i)"); - assertEval(Ignored.OutputFormatting, "deparse(quote(cat(-199.1234-5i)))"); assertEval(Ignored.OutputFormatting, "deparse(1.53160350210786e-322)"); assertEval("{ deparse(new.env()) }"); assertEval("{ k <- 2 ; deparse(k) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_digamma.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_digamma.java index c2556e91b4df924ed458f2775f265dc1ec42ada5..143dd8f317cca17573338c33f40569b878bf633f 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_digamma.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_digamma.java @@ -53,6 +53,6 @@ public class TestBuiltin_digamma extends TestBase { assertEval("{ digamma(c(100, 2.2)) }"); assertEval("{ digamma(FALSE) }"); assertEval("{ digamma(as.raw(1)) }"); - assertEval(Output.IgnoreErrorContext, "{ digamma(1+1i) }"); + assertEval("{ digamma(1+1i) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dim.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dim.java index b18378be4564e68d04ecec2de73f7837443fbcb7..d527dec5c882e06a46ffca647ed8d79738ee21ae 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dim.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dim.java @@ -186,7 +186,7 @@ public class TestBuiltin_dim extends TestBase { assertEval("{ x <- 1:4 ; f <- function() { x <- 1:4 ; dim(x) <<- c(2,2) } ; f() ; dim(x) }"); assertEval("{ x<-1:12; dim(x)<-c(12); x }"); - assertEval(Output.IgnoreWarningContext, "{ x<-1:12; dim(x)<-c(12+10i); x }"); + assertEval("{ x<-1:12; dim(x)<-c(12+10i); x }"); assertEval("{ x<-1:12; dim(x)<-c(as.raw(12)); x }"); assertEval("{ x<-1:12; dim(x)<-c(\"12\"); x }"); assertEval("{ x<-1:1; dim(x)<-c(TRUE); x }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java index 7cfe89a93f219a3551ecbd1db603a875de67aa65..30e927da8e3e374a2d622d882f1c950fce785be6 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java @@ -68,6 +68,6 @@ public class TestBuiltin_lgamma extends TestBase { assertEval("{ lgamma(c(100, 2.2)) }"); assertEval("{ lgamma(FALSE) }"); assertEval("{ lgamma(as.raw(1)) }"); - assertEval(Output.IgnoreErrorContext, "{ lgamma(1+1i) }"); + assertEval("{ lgamma(1+1i) }"); } } 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 c2389ce4841980d8c774e2251f32ce9cc25b1a74..9988eac042eb0b431b23b0e8d09dd63d67b35ebc 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 @@ -180,7 +180,7 @@ public class TestBuiltin_max extends TestBase { assertEval("{ is.logical(max(TRUE, FALSE)) }"); assertEval("{ is.logical(max(TRUE)) }"); assertEval("{ max(as.raw(42), as.raw(7)) }"); - assertEval(Output.IgnoreErrorContext, "{ max(42+42i, 7+7i) }"); + assertEval("{ max(42+42i, 7+7i) }"); assertEval("{ max(\"42\", \"7\") }"); assertEval("{ max(as.double(NA), na.rm=FALSE) }"); 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 beca4afa68c9c66c08c810f15394cc894ace305c..8cf0b4359dd248d93f856ad87479d6cdd89a5f2c 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 @@ -148,7 +148,7 @@ public class TestBuiltin_min extends TestBase { assertEval("{ is.logical(min(TRUE, FALSE)) }"); assertEval("{ is.logical(min(TRUE)) }"); assertEval("{ min(as.raw(42), as.raw(7)) }"); - assertEval(Output.IgnoreErrorContext, "{ min(42+42i, 7+7i) }"); + assertEval("{ min(42+42i, 7+7i) }"); assertEval("{ min(\"42\", \"7\") }"); assertEval("{ min(as.double(NA), na.rm=FALSE) }"); 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 de5976c0fd0aab29a2d541fae97574869857b9de..8d4de54a5b60042f9730f26db65bbdc902f13d56 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 @@ -34,7 +34,7 @@ public class TestBuiltin_signif extends TestBase { assertEval("{ signif(42.1234, \"2\") }"); assertEval("{ signif(42.1234, as.raw(2)) }"); - assertEval(Output.IgnoreErrorContext, "{ signif(42.1234, 42+7i) }"); + assertEval("{ signif(42.1234, 42+7i) }"); assertEval(Output.IgnoreErrorMessage, "{ signif(42.1234, character()) }"); assertEval("{ signif(\"42.1234\", 2 }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unserialize.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unserialize.java index ffe49c08587df723136734fbfc576bf594b48925..786a26fcd95d42e49bde626fbff43eb454c63004 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unserialize.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unserialize.java @@ -41,7 +41,64 @@ public class TestBuiltin_unserialize extends TestBase { @Test public void testserializeAndUnserializeClosure() { // N.B.: FastR does not preserve code formatting like GNU R does - assertEval(Ignored.OutputFormatting, "unserialize(serialize(function (x) { x }, NULL))"); + assertEval(Output.IgnoreWhitespace, "unserialize(serialize(function (x) { x }, NULL))"); assertEval("f <- function() x; e <- new.env(); e$x <- 123; environment(f) <- e; expr <- substitute({ FUN() }, list(FUN=f)); eval(expr); expr <- unserialize(serialize(expr, NULL)); eval(expr)"); } + + @Test + public void testunserialize() { + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(x), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(TRUE), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(FALSE), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote('asdf'), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(NA_character_), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(NA_complex_), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(NA_integer_), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(NA_real_), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(NA_character_ + NA_complex_ + NA_integer_ + NA_real_), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(111L), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(111+8i), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(111+11), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(a+b), connection=NULL))"); + + assertEval("options(keep.source=FALSE); unserialize(serialize(quote((a+b)), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote((a %asdf% b)), connection=NULL))"); + + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(foo(a,b,c)), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote({ foo(a,b,c) }), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(if (a) b else c), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(if (a) {b} else {c}), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(if ({a}) {b} else {c}), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(while (a) b), connection=NULL))"); + assertEval(Output.IgnoreWhitespace, "options(keep.source=FALSE); unserialize(serialize(quote(repeat {b; if (c) next else break}), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(if (a * 2 < 199) b + foo(x,y,foo=z+1,bar=)), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(\"bar\"), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote('baz'), connection=NULL))"); + assertEval("setClass('foo', slots = c(x='numeric', y='numeric')); t1 <- new('foo', x=4, y=c(77,88)); options(keep.source=FALSE); unserialize(serialize(t1, connection=NULL))"); + assertEval(Output.IgnoreWhitespace, "options(keep.source=FALSE); unserialize(serialize(quote(a(b(c(d(function (e, ...) { f(g)$h.i}))))), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(f(g)$h.i), connection=NULL))"); + assertEval(Output.ContainsReferences, "options(keep.source=FALSE); val <- new.env(hash=FALSE); unserialize(serialize(val, connection=NULL))"); + assertEval(Output.ContainsReferences, "options(keep.source=FALSE); val <- list(enclos = new.env(hash=FALSE)); unserialize(serialize(val, connection=NULL))"); + assertEval("options(keep.source=FALSE); val <- defaultPrototype(); unserialize(serialize(val, connection=NULL))"); + assertEval(Output.IgnoreWhitespace, "options(keep.source=FALSE); unserialize(serialize(quote(function() new(\"foo\", x)), connection=NULL))"); + assertEval(Output.IgnoreWhitespace, "options(keep.source=FALSE); unserialize(serialize(quote(function(x) { new(\"BAR\", x) }), connection=NULL))"); + assertEval(Output.IgnoreWhitespace, "options(keep.source=FALSE); unserialize(serialize(quote(function(x, ...) { new(\"BAR\", x) }), connection=NULL))"); + assertEval(Output.IgnoreWhitespace, "options(keep.source=FALSE); unserialize(serialize(quote(function(x,y) { new(\"BAR\", x) }), connection=NULL))"); + assertEval(Output.IgnoreWhitespace, "options(keep.source=FALSE); unserialize(serialize(quote(function(x,y) { TRUE }), connection=NULL))"); + assertEval(Output.IgnoreWhitespace, "options(keep.source=FALSE); unserialize(serialize(quote(function(x,y,...) { 1 }), connection=NULL))"); + assertEval(Output.IgnoreWhitespace, "options(keep.source=FALSE); unserialize(serialize(quote(function(x,y=1,...) { NA }), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { NA }), connection=NULL))"); + assertEval(Ignored.OutputFormatting, "options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { !!NA }), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { !1+5i }), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y=c(1,2,3),z=\"foo\",...) { !1+5i }), connection=NULL))"); + + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(function(x) { `+`(`(`(\"BAR\"), x) }), connection=NULL))"); + + assertEval(Output.ContainsReferences, "options(keep.source=FALSE); val <- new.env(hash=FALSE); val$a <- 'foo'; unserialize(serialize(val, connection=NULL))"); + assertEval(Output.ContainsReferences, "options(keep.source=FALSE); val <- new.env(hash=FALSE); val$b <- 123; unserialize(serialize(val, connection=NULL))"); + assertEval(Output.ContainsReferences, "options(keep.source=FALSE); val <- new.env(hash=FALSE); val$c <- 1233L; unserialize(serialize(val, connection=NULL))"); + assertEval(Output.ContainsReferences, "options(keep.source=FALSE); val <- new.env(hash=FALSE); val$d <- TRUE; unserialize(serialize(val, connection=NULL))"); + assertEval(Output.ContainsReferences, "options(keep.source=FALSE); val <- new.env(hash=FALSE); val$e <- 5+9i; unserialize(serialize(val, connection=NULL))"); + assertEval(Output.ContainsReferences, "options(keep.source=FALSE); val <- new.env(hash=FALSE); val$f <- NA; unserialize(serialize(val, connection=NULL))"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleSequences.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleSequences.java index 5687355087d7e0e3e406d54f609c68827d8cecae..dc4f1bdb0eade007de69ea3e2e28451cddeddc05 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleSequences.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleSequences.java @@ -50,12 +50,9 @@ public class TestSimpleSequences extends TestBase { assertEval("{ 10:1 }"); assertEval("{ (0-5):(0-9) }"); assertEval("{ 1.1:5.1 }"); - assertEval("{ 1:(1:3) }"); - - // these two test need proper handling of parentheses - assertEval(Output.IgnoreWarningContext, "{ (1:3):3 }"); - assertEval(Output.IgnoreWarningContext, "{ (1:3):(1:3) }"); + assertEval("{ (1:3):3 }"); + assertEval("{ (1:3):(1:3) }"); } @Test 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 7157061c65bb50848ff325e62e19759cddaea321..8d13bc5d5bb3ab54da393bd64f8f88332cf0d2d0 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 @@ -284,7 +284,7 @@ public class TestSimpleVectors extends TestBase { assertEval(Output.IgnoreErrorContext, "{ x<-c(1,2); x[[c(\"a\", \"b\")]] }"); assertEval("{ x<-1:2; x[c(TRUE, TRUE)] }"); assertEval(Output.IgnoreErrorContext, "{ x<-1:2; x[[c(TRUE, TRUE)]] }"); - assertEval(Output.IgnoreErrorContext, "{ x<-1:2; dim(x)<-c(1,2); x[2+2i, 2+2i] }"); + assertEval("{ x<-1:2; dim(x)<-c(1,2); x[2+2i, 2+2i] }"); assertEval("{ x<-1:2; dim(x)<-c(1,2); u<-2+2i; x[[u, u]] }"); assertEval("{ x<-2; x[NULL] }"); assertEval(Output.IgnoreErrorContext, "{ x<-2; x[[NULL]] }"); @@ -428,16 +428,16 @@ public class TestSimpleVectors extends TestBase { assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[[c(FALSE,TRUE,TRUE)]]<-c(42,43); x }"); assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[[complex()]]<-c(42,43); x }"); assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[[c(1+1i)]]<-integer(); x }"); - assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[[c(1+1i)]]<-c(42); x }"); + assertEval("{ x<-1:4; dim(x)<-c(2,2); x[[c(1+1i)]]<-c(42); x }"); assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[[c(1+1i)]]<-c(42,43); x }"); assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[[c(1+1i,42+7i,3+3i)]]<-c(42,43); x }"); assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[[c(0,42+7i)]]<-c(42,43); x }"); assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[c(1+1i)]<-integer(); x }"); - assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[c(1+1i)]<-c(42); x }"); + assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1+1i)]<-c(42); x }"); assertEval("{ x<-1:4; dim(x)<-c(2,2); x[complex()]<-c(42,43); x }"); - assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[c(1+1i)]<-c(42,43); x }"); - assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[c(1+1i,42+7i,3+3i)]<-c(42,43); x }"); - assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[c(0,42+7i)]<-c(42,43); x }"); + assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1+1i)]<-c(42,43); x }"); + assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1+1i,42+7i,3+3i)]<-c(42,43); x }"); + assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(0,42+7i)]<-c(42,43); x }"); assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[[c(0,0,42+71)]]<-c(42,43); x }"); assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[[c(as.raw(integer()))]]<-c(42,43); x }"); assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[[c(as.raw(42))]]<-integer(); x }"); @@ -771,14 +771,14 @@ public class TestSimpleVectors extends TestBase { @Test public void testComplexIndex() { assertEval(Output.IgnoreErrorMessage, "{ x<-c(1,2,3,4); x[[1+1i]]<-integer() }"); - assertEval(Output.IgnoreErrorContext, "{ x<-c(1,2,3,4); x[[1+1i]]<-c(1) }"); + assertEval("{ x<-c(1,2,3,4); x[[1+1i]]<-c(1) }"); assertEval(Output.IgnoreErrorMessage, "{ x<-c(1,2,3,4); x[[1+1i]]<-c(1,2) }"); assertEval(Output.IgnoreErrorMessage, "{ x<-c(1,2,3,4); x[[1+1i]]<-c(1,2,3) }"); - assertEval(Output.IgnoreErrorContext, "{ x<-c(1,2,3,4); x[1+1i]<-NULL }"); - assertEval(Output.IgnoreErrorContext, "{ x<-c(1,2,3,4); x[1+1i]<-integer() }"); - assertEval(Output.IgnoreErrorContext, "{ x<-c(1,2,3,4); x[1+1i]<-c(1) }"); - assertEval(Output.IgnoreErrorContext, "{ x<-c(1,2,3,4); x[1+1i]<-c(1,2) }"); - assertEval(Output.IgnoreErrorContext, "{ x<-c(1,2,3,4); x[1+1i]<-c(1,2,3) }"); + assertEval("{ x<-c(1,2,3,4); x[1+1i]<-NULL }"); + assertEval("{ x<-c(1,2,3,4); x[1+1i]<-integer() }"); + assertEval("{ x<-c(1,2,3,4); x[1+1i]<-c(1) }"); + assertEval("{ x<-c(1,2,3,4); x[1+1i]<-c(1,2) }"); + assertEval("{ x<-c(1,2,3,4); x[1+1i]<-c(1,2,3) }"); assertEval(Output.IgnoreErrorMessage, "{ x<-c(1,2,3,4); dim(x)<-c(2,2); x[[1+1i, 1]]<-integer() }"); assertEval(Output.IgnoreErrorContext, "{ x<-c(1,2,3,4); dim(x)<-c(2,2); x[[1+1i, 1]]<-7 }"); @@ -787,16 +787,16 @@ public class TestSimpleVectors extends TestBase { assertEval(Output.IgnoreErrorContext, "{ x<-c(1,2,3,4); dim(x)<-c(2,2); x[1+1i, 1]<-7 }"); assertEval(Output.IgnoreErrorContext, "{ x<-c(1,2,3,4); dim(x)<-c(2,2); x[1+1i, 1]<-c(7,42) }"); - assertEval(Output.IgnoreErrorContext, "{ x<-list(1,2,3,4); x[[1+1i]]<-NULL }"); - assertEval(Output.IgnoreErrorContext, "{ x<-list(1,2,3,4); x[[1+1i]]<-integer() }"); - assertEval(Output.IgnoreErrorContext, "{ x<-list(1,2,3,4); x[[1+1i]]<-c(1) }"); - assertEval(Output.IgnoreErrorContext, "{ x<-list(1,2,3,4); x[[1+1i]]<-c(1,2) }"); - assertEval(Output.IgnoreErrorContext, "{ x<-list(1,2,3,4); x[[1+1i]]<-c(1,2,3) }"); - assertEval(Output.IgnoreErrorContext, "{ x<-list(1,2,3,4); x[1+1i]<-NULL }"); - assertEval(Output.IgnoreErrorContext, "{ x<-list(1,2,3,4); x[1+1i]<-integer() }"); - assertEval(Output.IgnoreErrorContext, "{ x<-list(1,2,3,4); x[1+1i]<-c(1) }"); - assertEval(Output.IgnoreErrorContext, "{ x<-list(1,2,3,4); x[1+1i]<-c(1,2) }"); - assertEval(Output.IgnoreErrorContext, "{ x<-list(1,2,3,4); x[1+1i]<-c(1,2,3) }"); + assertEval("{ x<-list(1,2,3,4); x[[1+1i]]<-NULL }"); + assertEval("{ x<-list(1,2,3,4); x[[1+1i]]<-integer() }"); + assertEval("{ x<-list(1,2,3,4); x[[1+1i]]<-c(1) }"); + assertEval("{ x<-list(1,2,3,4); x[[1+1i]]<-c(1,2) }"); + assertEval("{ x<-list(1,2,3,4); x[[1+1i]]<-c(1,2,3) }"); + assertEval("{ x<-list(1,2,3,4); x[1+1i]<-NULL }"); + assertEval("{ x<-list(1,2,3,4); x[1+1i]<-integer() }"); + assertEval("{ x<-list(1,2,3,4); x[1+1i]<-c(1) }"); + assertEval("{ x<-list(1,2,3,4); x[1+1i]<-c(1,2) }"); + assertEval("{ x<-list(1,2,3,4); x[1+1i]<-c(1,2,3) }"); assertEval(Output.IgnoreErrorMessage, "{ x<-list(1,2,3,4); dim(x)<-c(2,2); x[[1+1i, 1]]<-NULL }"); assertEval(Output.IgnoreErrorContext, "{ x<-list(1,2,3,4); dim(x)<-c(2,2); x[[1+1i, 1]]<-integer() }"); @@ -1352,10 +1352,10 @@ public class TestSimpleVectors extends TestBase { assertEval(Output.IgnoreErrorContext, "{ x <- c(a=1,b=2) ; x[[c(\"a\",\"a\")]] }"); assertEval("{ x <- list(1,2) ; x[[c(\"a\",\"a\")]] }"); assertEval("{ x <- list(a=1,b=1:3) ; x[[c(\"b\",\"a\")]] }"); - assertEval(Output.IgnoreErrorContext, "{ x <- list(a=1,b=1:3) ; x[[2+3i]] }"); + assertEval("{ x <- list(a=1,b=1:3) ; x[[2+3i]] }"); assertEval("{ x <- list(a=1,b=1:3) ; f <- function(i) { x[[i]] } ; f(c(2,2)) ; f(2+3i) }"); assertEval("{ x <- 1:3; x[list(2,3)] }"); - assertEval(Output.IgnoreErrorContext, "{ x <- 1:3; x[function(){3}] }"); + assertEval("{ x <- 1:3; x[function(){3}] }"); assertEval(Output.IgnoreErrorMessage, "{ x <- 1:2; x[[list()]] }"); assertEval(Output.IgnoreErrorMessage, "{ x <- 1:2; x[[list(-0,-1)]] }"); assertEval("{ x <- 1:2; x[[list(0)]] }"); @@ -1748,7 +1748,7 @@ public class TestSimpleVectors extends TestBase { assertEval("{ b <- c(1,2,5) ; b[c(TRUE,FALSE,FALSE)] <- NULL ; b }"); assertEval("{ b <- c(1,2,5) ; b[logical()] <- NULL ; b }"); - assertEval(Output.IgnoreErrorContext, "{ b <- c(1,2,5) ; b[c(TRUE,NA,TRUE)] <- list(TRUE,1+2i) ; b }"); + assertEval("{ b <- c(1,2,5) ; b[c(TRUE,NA,TRUE)] <- list(TRUE,1+2i) ; b }"); assertEval("{ b <- c(1,2,5) ; b[c(TRUE,FALSE,TRUE)] <- list(TRUE,1+2i) ; b }"); assertEval("{ b <- list(1,2,5) ; dim(b) <- c(1,3) ; b[c(TRUE,FALSE,TRUE)] <- list(TRUE,1+2i) ; b }"); assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,c(TRUE,FALSE,TRUE),5:6) ; x <- list(1,2,5) ; dim(x) <- c(1,3) ; f(x, c(FALSE,TRUE,TRUE), list(TRUE,1+2i)) }"); @@ -1848,7 +1848,7 @@ public class TestSimpleVectors extends TestBase { assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(c(\"a\",\"b\",\"c\"),c(TRUE,FALSE),c(\"A\",\"X\")) ; f(1:3,c(TRUE,FALSE),4) }"); assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(c(\"a\",\"b\",\"c\"),c(TRUE,FALSE),c(\"A\",\"X\")) ; f(c(\"A\",\"X\"),c(TRUE,FALSE),4) }"); assertEval("{ b <- c(\"a\",\"b\",\"c\") ; b[c(TRUE,FALSE,TRUE)] <- c(1+2i,3+4i) ; b }"); - assertEval(Output.IgnoreErrorContext, "{ b <- as.raw(1:5) ; b[c(TRUE,FALSE,TRUE)] <- c(1+2i,3+4i) ; b }"); + assertEval("{ b <- as.raw(1:5) ; b[c(TRUE,FALSE,TRUE)] <- c(1+2i,3+4i) ; b }"); assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(c(\"a\",\"b\",\"c\"),c(TRUE,FALSE),c(\"A\",\"X\")) ; f(f,c(TRUE,FALSE),4) }"); assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(c(\"a\",\"b\",\"c\"),c(TRUE,FALSE),c(\"A\",\"X\")) ; f(c(\"A\",\"X\"),c(TRUE,FALSE),f) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_qgamma.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_qgamma.java new file mode 100644 index 0000000000000000000000000000000000000000..86baa6fa4cadbe428ab8215f505c9dea64aec8ad --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_qgamma.java @@ -0,0 +1,45 @@ +/* + * 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.stats; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestExternal_qgamma extends TestBase { + @Test + public void testQgamma() { + assertEval("qgamma(1, 1)"); + assertEval("qgamma(0.1, 1)"); + assertEval("qgamma(0, 1)"); + assertEval("qgamma(0.1, 10, rate=2, lower.tail=FALSE)"); + assertEval("qgamma(log(1.2e-8), 10, log.p=TRUE)"); + assertEval("qgamma(c(0.1, 0.5, 0.99), c(10, 20), 7)"); + } + + @Test + public void testQgammaWrongArgs() { + assertEval("qgamma(10, 1)"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbinom.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbinom.java new file mode 100644 index 0000000000000000000000000000000000000000..79296c9ac3e58bd59a3d54e33bd25095acc260cc --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbinom.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.library.stats; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestExternal_rbinom extends TestBase { + @Test + public void testRbinom() { + assertEval("set.seed(42); rbinom(10, 10, 0.5)"); + assertEval("set.seed(42); rbinom('10', 10, 0.5)"); + assertEval(Output.IgnoreWarningContext, "set.seed(42); rbinom('aa', 10, 0.5)"); + assertEval("set.seed(42); rbinom(10, 2:10, c(0.1, 0.5, 0.9))"); + assertEval("set.seed(42); rbinom(1:10, 2:10, c(0.1, 0.5, 0.9))"); + assertEval("set.seed(42); rbinom(c(1,2), 11:12, c(0.1, 0.5, 0.9))"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rnorm.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rnorm.java new file mode 100644 index 0000000000000000000000000000000000000000..1bd9882bfcde589cdb3fce85d3a8de27d0432d0f --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rnorm.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.library.stats; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestExternal_rnorm extends TestBase { + @Test + public void testRnorm() { + assertEval("set.seed(42); rnorm(10, 10, 10)"); + assertEval("set.seed(42); rnorm('10', 10, 5)"); + assertEval(Output.IgnoreWarningContext, "set.seed(42); rnorm('aa', 10, 0.5)"); + assertEval("set.seed(42); rnorm(10, 2:10, c(0.1, 0.5, 0.9))"); + assertEval("set.seed(42); rnorm(1:10, 2:10, c(0.1, 0.5, 0.9))"); + assertEval("set.seed(42); rnorm(c(1,2), 11:12, c(0.1, 0.5, 0.9))"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_runif.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_runif.java new file mode 100644 index 0000000000000000000000000000000000000000..ad117436f0b49f14a365a15ae38563b7b26ca3fc --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_runif.java @@ -0,0 +1,35 @@ +/* + * 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.stats; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestExternal_runif extends TestBase { + @Test + public void testRunif() { + assertEval("set.seed(1); runif(5);"); + assertEval("set.seed(1); runif(5, 10, 2.5);"); + } +} diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides index 56b7c99b8a94b8c07f41e393e08bde5134d5936e..9f34ed75c3493461aeec8aa2305e56002c1478ea 100644 --- a/mx.fastr/copyrights/overrides +++ b/mx.fastr/copyrights/overrides @@ -50,6 +50,7 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rbinom.java, com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Rnorm.java,gnu_r.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java,gnu_r_splines.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctions.java,gnu_r_gentleman_ihaka.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandGenerationFunctions.java,gnu_r_gentleman_ihaka.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsUtil.java,gnu_r_ihaka.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/TOMS708.java,gnu_r.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java,gnu_r.copyright diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py index 971b6743e1025e3a4776a7cc05b2b9416a8be764..08c061c0ba69413909904e776bd5db9788a25db8 100644 --- a/mx.fastr/suite.py +++ b/mx.fastr/suite.py @@ -28,7 +28,7 @@ suite = { "suites" : [ { "name" : "truffle", - "version" : "3c34543a8b7ff5edd74b76aafbeb3af52bd4afe7", + "version" : "f0c06d466056ad23e05aa3d21b98405cd72f117b", "urls" : [ {"url" : "https://github.com/graalvm/truffle", "kind" : "git"}, {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},