From 6c7cd191d66c8fbfc6b3ea4ad01e491d85b000cd Mon Sep 17 00:00:00 2001 From: Tomas Stupka <tomas.stupka@oracle.com> Date: Fri, 10 Feb 2017 13:39:39 +0100 Subject: [PATCH] added cast pipelines to SubstituteDirect, Substitute, TypeConvert, Dqrcf, SplineCoef buildins --- .../r/library/methods/SubstituteDirect.java | 41 ++++++++-- .../r/library/stats/SplineFunctions.java | 56 ++++++++++++-- .../truffle/r/library/utils/TypeConvert.java | 23 +++++- .../r/nodes/builtin/base/Substitute.java | 33 ++++++-- .../r/nodes/builtin/base/foreign/Dqrcf.java | 37 ++++----- .../base/foreign/FortranAndCFunctions.java | 2 +- .../r/nodes/builtin/RList2EnvNode.java | 11 ++- .../com/oracle/truffle/r/runtime/RError.java | 3 + .../test/builtins/TestBuiltin_substitute.java | 25 +++++++ .../library/methods/TestSubstituteDirect.java | 75 +++++++++++++++++++ .../library/stats/TestSplineFunctions.java | 71 ++++++++++++++++++ .../r/test/library/utils/TestTypeConvert.java | 37 +++++++++ mx.fastr/mx_fastr.py | 2 +- 13 files changed, 370 insertions(+), 46 deletions(-) create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/methods/TestSubstituteDirect.java create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestSplineFunctions.java diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java index 420e634f2e..e1a2b1bac6 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java @@ -27,19 +27,24 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.RASTUtils; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.nodes.builtin.RList2EnvNode; import com.oracle.truffle.r.runtime.RError; +import static com.oracle.truffle.r.runtime.RError.Message.INVALID_LIST_FOR_SUBSTITUTION; +import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import com.oracle.truffle.r.runtime.RSubstitute; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.env.REnvironment; public abstract class SubstituteDirect extends RExternalBuiltinNode.Arg2 { static { - Casts.noCasts(SubstituteDirect.class); + Casts casts = new Casts(SubstituteDirect.class); + casts.arg(1).defaultError(SHOW_CALLER, INVALID_LIST_FOR_SUBSTITUTION).mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(REnvironment.class))); } @Specialization @@ -53,18 +58,40 @@ public abstract class SubstituteDirect extends RExternalBuiltinNode.Arg2 { } } - @Specialization + @Specialization(guards = {"list.getNames() == null || list.getNames().getLength() == 0"}) + @TruffleBoundary + protected static Object substituteDirect(Object object, RList list) { + return substituteDirect(object, createNewEnvironment()); + } + + @Specialization(guards = {"list.getNames() != null", "list.getNames().getLength() > 0"}) @TruffleBoundary protected static Object substituteDirect(Object object, RList list, - @Cached("new()") RList2EnvNode list2Env) { - REnvironment env = RDataFactory.createNewEnv(null); - env.setParent(REnvironment.baseEnv()); - list2Env.execute(list, env); - return substituteDirect(object, env); + @Cached("createList2EnvNode()") RList2EnvNode list2Env) { + return substituteDirect(object, createEnvironment(list, list2Env)); } @Fallback protected Object substituteDirect(@SuppressWarnings("unused") Object object, @SuppressWarnings("unused") Object env) { throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); } + + @TruffleBoundary + public static REnvironment createNewEnvironment() { + return createEnvironment(null, null); + } + + @TruffleBoundary + public static REnvironment createEnvironment(RList list, RList2EnvNode list2Env) { + REnvironment env = RDataFactory.createNewEnv(null); + env.setParent(REnvironment.baseEnv()); + if (list2Env != null) { + list2Env.execute(list, env); + } + return env; + } + + protected static RList2EnvNode createList2EnvNode() { + return new RList2EnvNode(true); + } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java index a16c52363c..d6b11cfc74 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java @@ -13,12 +13,22 @@ package com.oracle.truffle.r.library.stats; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RInternalError; +import static com.oracle.truffle.r.runtime.RError.Message.NA_INTRODUCED_COERCION; +import static com.oracle.truffle.r.runtime.RError.NO_CALLER; +import static com.oracle.truffle.r.runtime.RRuntime.INT_NA; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.nmath.RMath; @@ -32,12 +42,38 @@ import com.oracle.truffle.r.runtime.nmath.RMath; public class SplineFunctions { public abstract static class SplineCoef extends RExternalBuiltinNode.Arg3 { + static { + Casts casts = new Casts(SplineCoef.class); + casts.arg(0).mapNull(constant(INT_NA)).mapIf(numericValue(), + chain(asIntegerVector()).with(findFirst().integerElement(INT_NA)).end(), + chain(asIntegerVector()).with(findFirst().integerElement(INT_NA)).with( + Predef.shouldBe(integerValue(), NO_CALLER, NA_INTRODUCED_COERCION)).end()); + casts.arg(1).allowMissing().asDoubleVector(); + casts.arg(2).allowMissing().asDoubleVector(); + } + + @Specialization + @TruffleBoundary + protected Object splineCoef(int method, RAbstractDoubleVector x, RAbstractDoubleVector y) { + return SplineFunctions.splineCoef(method, x.materialize(), y.materialize()); + } @Specialization @TruffleBoundary - protected Object splineCoef(Object method, RAbstractDoubleVector x, RAbstractDoubleVector y) { - int methodInt = castInt(castVector(method)); - return SplineFunctions.splineCoef(methodInt, x.materialize(), y.materialize()); + protected Object splineCoef(int method, RAbstractDoubleVector x, RNull y) { + return SplineFunctions.splineCoef(method, x.materialize(), RDataFactory.createDoubleVector(0)); + } + + @Specialization + @TruffleBoundary + protected Object splineCoef(int method, RNull x, RAbstractDoubleVector y) { + return SplineFunctions.splineCoef(method, RDataFactory.createDoubleVector(0), y.materialize()); + } + + @Specialization + @TruffleBoundary + protected Object splineCoef(int method, RNull x, RNull y) { + return SplineFunctions.splineCoef(method, RDataFactory.createDoubleVector(0), RDataFactory.createDoubleVector(0)); } } @@ -99,7 +135,9 @@ public class SplineFunctions { double[] e = new double[n]; - RInternalError.guarantee(n >= 2 && y[0] == y[n - 1], "periodic spline: domain error"); + if (n < 2 || y[0] != y[n - 1]) { + return; + } if (n == 2) { b[0] = 0.0; @@ -215,7 +253,9 @@ public class SplineFunctions { int i; double t; - RInternalError.guarantee(n >= 2, "periodic spline: domain error"); + if (n < 2) { + return; + } if (n < 3) { t = (y[1] - y[0]); @@ -289,7 +329,9 @@ public class SplineFunctions { int i; double t; - RInternalError.guarantee(n >= 2, "periodic spline: domain error"); + if (n < 2) { + return; + } if (n < 3) { t = (y[1] - y[0]); diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java index fb7fbf6c6a..27d158bbc8 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java @@ -27,8 +27,20 @@ import java.util.TreeSet; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asLogicalVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import static com.oracle.truffle.r.runtime.RError.Message.FIRST_ARGUMENT_MUST_BE_CHARACTER; +import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARG; +import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import com.oracle.truffle.r.runtime.RRuntime; +import static com.oracle.truffle.r.runtime.RRuntime.LOGICAL_FALSE; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RIntVector; @@ -41,7 +53,12 @@ public abstract class TypeConvert extends RExternalBuiltinNode.Arg5 { @Child private SetFixedAttributeNode setLevelsAttrNode = SetFixedAttributeNode.create(RRuntime.LEVELS_ATTR_KEY); static { - Casts.noCasts(TypeConvert.class); + Casts casts = new Casts(TypeConvert.class); + casts.arg(0).mustBe(stringValue(), SHOW_CALLER, FIRST_ARGUMENT_MUST_BE_CHARACTER).asStringVector(); + casts.arg(1).mustBe(stringValue(), SHOW_CALLER, INVALID_ARG, "'na.strings'").asStringVector(); + casts.arg(2).mapIf(logicalValue(), + chain(asLogicalVector()).with(findFirst().logicalElement(LOGICAL_FALSE)).with(toBoolean()).end(), + chain(map(constant(LOGICAL_FALSE))).with(toBoolean()).end()); } private static boolean isNA(String s, RAbstractStringVector naStrings) { @@ -109,7 +126,7 @@ public abstract class TypeConvert extends RExternalBuiltinNode.Arg5 { } @Specialization - protected Object typeConvert(RAbstractStringVector x, RAbstractStringVector naStrings, byte asIs, @SuppressWarnings("unused") Object dec, @SuppressWarnings("unused") Object numeral) { + protected Object typeConvert(RAbstractStringVector x, RAbstractStringVector naStrings, boolean asIs, @SuppressWarnings("unused") Object dec, @SuppressWarnings("unused") Object numeral) { if (x.getLength() == 0) { return RDataFactory.createEmptyLogicalVector(); } @@ -164,7 +181,7 @@ public abstract class TypeConvert extends RExternalBuiltinNode.Arg5 { } // fall through target - conversion to int, double or logical failed - if (asIs == RRuntime.LOGICAL_TRUE) { + if (asIs) { return x; } else { // create a factor diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java index 395271e222..8f75d38052 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java @@ -26,20 +26,25 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.library.methods.SubstituteDirect; import com.oracle.truffle.r.nodes.RASTUtils; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.RList2EnvNode; import com.oracle.truffle.r.nodes.control.IfNode; -import com.oracle.truffle.r.runtime.RError; +import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ENVIRONMENT_SPECIFIED; import com.oracle.truffle.r.runtime.RSubstitute; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.env.REnvironment; @RBuiltin(name = "substitute", kind = PRIMITIVE, parameterNames = {"expr", "env"}, nonEvalArgs = 0, behavior = COMPLEX) @@ -48,7 +53,8 @@ public abstract class Substitute extends RBuiltinNode { @Child private Quote quote; static { - Casts.noCasts(Substitute.class); + Casts casts = new Casts(Substitute.class); + casts.arg(1).allowNullAndMissing().defaultError(INVALID_ENVIRONMENT_SPECIFIED).mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(REnvironment.class))); } @Specialization @@ -56,19 +62,25 @@ public abstract class Substitute extends RBuiltinNode { return doSubstituteWithEnv(expr, REnvironment.frameToEnvironment(frame.materialize())); } + @Specialization + protected Object doSubstitute(VirtualFrame frame, RPromise expr, @SuppressWarnings("unused") RNull env) { + return doSubstituteWithEnv(expr, REnvironment.frameToEnvironment(frame.materialize())); + } + @Specialization protected Object doSubstitute(RPromise expr, REnvironment env) { return doSubstituteWithEnv(expr, env); } - @Specialization + @Specialization(guards = {"list.getNames() == null || list.getNames().getLength() == 0"}) protected Object doSubstitute(RPromise expr, RList list) { - return doSubstituteWithEnv(expr, REnvironment.createFromList(list, REnvironment.baseEnv())); + return doSubstituteWithEnv(expr, SubstituteDirect.createNewEnvironment()); } - @Fallback - protected Object doSubstitute(@SuppressWarnings("unused") Object expr, @SuppressWarnings("unused") Object x) { - throw RError.error(this, RError.Message.INVALID_ENVIRONMENT); + @Specialization(guards = {"list.getNames() != null", "list.getNames().getLength() > 0"}) + protected Object doSubstitute(RPromise expr, RList list, + @Cached("createList2EnvNode()") RList2EnvNode list2Env) { + return doSubstituteWithEnv(expr, SubstituteDirect.createEnvironment(list, list2Env)); } /** @@ -99,4 +111,9 @@ public abstract class Substitute extends RBuiltinNode { // so get the actual expression (AST) from that return RASTUtils.createLanguageElement(RSubstitute.substitute(env, expr.getRep())); } + + protected static RList2EnvNode createList2EnvNode() { + return new RList2EnvNode(true); + } + } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java index 6941258c6b..d10efffa16 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java @@ -11,10 +11,12 @@ */ package com.oracle.truffle.r.nodes.builtin.base.foreign; +import com.oracle.truffle.api.dsl.Specialization; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RList; @@ -24,44 +26,43 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.ffi.RApplRFFI; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; -public final class Dqrcf extends RExternalBuiltinNode { +public abstract class Dqrcf extends RExternalBuiltinNode.Arg8 { @Child private RApplRFFI.RApplRFFINode rApplRFFINode = RFFIFactory.getRFFI().getRApplRFFI().createRApplRFFINode(); private static final String E = RRuntime.NAMES_ATTR_EMPTY_VALUE; private static final RStringVector DQRCF_NAMES = RDataFactory.createStringVector(new String[]{E, E, E, E, E, E, "coef", "info"}, RDataFactory.COMPLETE_VECTOR); static { - Casts.noCasts(Dqrcf.class); + Casts casts = new Casts(Dqrcf.class); + casts.arg(0).mustBe(doubleValue()).asDoubleVector(); + casts.arg(1).mustBe(integerValue()).asIntegerVector().findFirst(); + casts.arg(2).mustBe(integerValue()).asIntegerVector().findFirst(); + casts.arg(3).mustBe(doubleValue()).asDoubleVector(); + casts.arg(4).mustBe(doubleValue()).asDoubleVector(); + casts.arg(5).mustBe(integerValue()).asIntegerVector().findFirst(); + casts.arg(6).mustBe(doubleValue()).asDoubleVector(); + casts.arg(7).mustBe(integerValue()).asIntegerVector(); } - @Override - public RList call(RArgsValuesAndNames args) { - Object[] argValues = args.getArguments(); + @Specialization + public RList dqrcf(RAbstractDoubleVector xVec, int nx, int k, RAbstractDoubleVector qrauxVec, RAbstractDoubleVector yVec, int ny, RAbstractDoubleVector bVec, RAbstractIntVector infoVec) { try { - RAbstractDoubleVector xVec = (RAbstractDoubleVector) argValues[0]; - int n = argValues[1] instanceof Integer ? (int) argValues[1] : ((RAbstractIntVector) argValues[1]).getDataAt(0); - RAbstractIntVector k = (RAbstractIntVector) argValues[2]; - RAbstractDoubleVector qrauxVec = (RAbstractDoubleVector) argValues[3]; - RAbstractDoubleVector yVec = (RAbstractDoubleVector) argValues[4]; - int ny = argValues[5] instanceof Integer ? (int) argValues[5] : ((RAbstractIntVector) argValues[5]).getDataAt(0); - RAbstractDoubleVector bVec = (RAbstractDoubleVector) argValues[6]; - RAbstractIntVector infoVec = (RAbstractIntVector) argValues[7]; double[] x = xVec.materialize().getDataTemp(); double[] qraux = qrauxVec.materialize().getDataTemp(); double[] y = yVec.materialize().getDataTemp(); double[] b = bVec.materialize().getDataTemp(); int[] info = infoVec.materialize().getDataTemp(); - rApplRFFINode.dqrcf(x, n, k.getDataAt(0), qraux, y, ny, b, info); + rApplRFFINode.dqrcf(x, nx, k, qraux, y, ny, b, info); RDoubleVector coef = RDataFactory.createDoubleVector(b, RDataFactory.COMPLETE_VECTOR); coef.copyAttributesFrom(bVec); // @formatter:off Object[] data = new Object[]{ RDataFactory.createDoubleVector(x, RDataFactory.COMPLETE_VECTOR), - argValues[1], - k.copy(), + nx, + k, RDataFactory.createDoubleVector(qraux, RDataFactory.COMPLETE_VECTOR), RDataFactory.createDoubleVector(y, RDataFactory.COMPLETE_VECTOR), - argValues[5], + ny, coef, RDataFactory.createIntVector(info, RDataFactory.COMPLETE_VECTOR), }; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java index 29a1c389bc..d3d6625fa2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java @@ -203,7 +203,7 @@ public class FortranAndCFunctions { case "dqrdc2": return Dqrdc2.create(); case "dqrcf": - return new Dqrcf(); + return DqrcfNodeGen.create(); default: return null; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java index a50458a51a..cc2264b97c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java @@ -33,6 +33,15 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; * Abstracted for use by other nodes that need to convert a list into an environment. */ public final class RList2EnvNode extends RBaseNode { + private final boolean ignoreMissingNames; + + public RList2EnvNode() { + this(false); + } + + public RList2EnvNode(boolean ignoreMissingNames) { + this.ignoreMissingNames = ignoreMissingNames; + } @TruffleBoundary public REnvironment execute(RAbstractListVector list, REnvironment env) { @@ -45,7 +54,7 @@ public final class RList2EnvNode extends RBaseNode { } for (int i = list.getLength() - 1; i >= 0; i--) { String name = names.getDataAt(i); - if (name.length() == 0) { + if (!ignoreMissingNames && name.length() == 0) { throw RError.error(this, RError.Message.ZERO_LENGTH_VARIABLE); } // in case of duplicates, last element in list wins diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java index 9f4d41c7fe..58bc36b5d7 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java @@ -409,6 +409,7 @@ public final class RError extends RuntimeException { PROMISE_CYCLE("promise already under evaluation: recursive default argument reference or earlier problems?"), MISSING_ARGUMENTS("'missing' can only be used for arguments"), INVALID_ENVIRONMENT("invalid environment"), + INVALID_ENVIRONMENT_SPECIFIED("invalid environment specified"), ENVIR_NOT_LENGTH_ONE("numeric 'envir' arg not of length one"), FMT_NOT_CHARACTER("'fmt' is not a character vector"), UNSUPPORTED_TYPE("unsupported type"), @@ -559,6 +560,7 @@ public final class RError extends RuntimeException { INVALID_LOGICAL("'%s' must be TRUE or FALSE"), INVALID_FORMAT_STRING("invalid format '%s'; use format %%s for character objects"), MUST_BE_CHARACTER("'%s' must be of mode character"), + FIRST_ARGUMENT_MUST_BE_CHARACTER("the first argument must be of mode character"), ALL_ATTRIBUTES_NAMES("all attributes must have names [%d does not]"), INVALID_REGEXP("invalid regular expression '%s'"), COERCING_ARGUMENT("coercing argument of type '%s' to %s"), @@ -598,6 +600,7 @@ public final class RError extends RuntimeException { NOT_A_SYMBOL("not a symbol"), CANNOT_SET_PARENT("cannot set the parent of the empty environment"), INVALID_OR_UNIMPLEMENTED_ARGUMENTS("invalid or unimplemented arguments"), + INVALID_LIST_FOR_SUBSTITUTION("invalid list for substitution"), NOTHING_TO_LINK("nothing to link"), FROM_TO_DIFFERENT("'from' and 'to' are of different lengths"), NA_IN_FOREIGN_FUNCTION_CALL("NAs in foreign function call (arg %d)"), diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substitute.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substitute.java index 871968ec0b..ad2e9940d3 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substitute.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substitute.java @@ -87,5 +87,30 @@ public class TestBuiltin_substitute extends TestBase { assertEval("f<-function(x,name) substitute(x$name <- 5); f(foo, bar); foo <- new.env(); eval(f(foo,bar)); foo$bar"); assertEval("f<-function(x,name) substitute(x@name); f(foo, bar); setClass('cl', representation(bar='numeric')); foo <- new('cl'); foo@bar <- 1; eval(f(foo,bar))"); assertEval("f<-function(x,name) substitute(x@name <- 5); f(foo, bar); setClass('cl', representation(bar='numeric')); foo <- new('cl'); eval(f(foo,bar)); foo@bar"); + + assertEval("substitute(1, 1)"); + assertEval("substitute(1, 1, 1)"); + assertEval("substitute(expr=1, env=1)"); + + assertEval("substitute(1, NULL)"); + assertEval("substitute(1, NA)"); + assertEval("substitute(1, c(list(1)))"); + assertEval("substitute(1, list(c(list(1))))"); + assertEval("substitute(1, list(list(1)))"); + + assertEval("a<-substitute(quote(x+1), NULL); a"); + assertEval("a<-substitute(quote(x+1), NA); a"); + assertEval("a<-substitute(quote(x+1), list(1)); a"); + assertEval("a<-substitute(quote(x+1), list(x=1)); a"); + assertEval("a<-substitute(quote(x+1), list(y=1)); a"); + assertEval("a<-substitute(quote(x+1), c(list(x=1), 'breakme')); a"); + assertEval("a<-substitute(quote(x+1), c(c(list(x=1)))); a"); + assertEval("a<-substitute(quote(x+1), list(c(c(list(x=1))))); a"); + assertEval("a<-substitute(quote(x+1), list(list(x=1))); a"); + assertEval("a<-substitute(quote(x+1), c(list(x=1, 1))); a"); + assertEval("a<-substitute(quote(x+y), c(list(x=1), list(y=1))); a"); + assertEval("substitute(quote(x+1), environment())"); + assertEval("f<-function() {}; substitute(quote(x+1), f)"); + assertEval("substitute(quote(x+1), setClass('a'))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/methods/TestSubstituteDirect.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/methods/TestSubstituteDirect.java new file mode 100644 index 0000000000..4ab7f98157 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/methods/TestSubstituteDirect.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.test.library.methods; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestSubstituteDirect extends TestBase { + + @Test + public void basicTests() { + assertEval("substituteDirect(NULL, list(x=1))"); + assertEval("substituteDirect(NA, list(x=1))"); + assertEval("substituteDirect(environment(), list(x=1))"); + assertEval("substituteDirect(1, 1)"); + assertEval("substituteDirect(1, 1, 1)"); + assertEval("substituteDirect(object=1, frame=1)"); + assertEval("substituteDirect(object=1, frame=1, cleanFunction=1)"); + + assertEval("substituteDirect(1, frame=NULL)"); + assertEval("substituteDirect(1, frame=NA)"); + assertEval("substituteDirect(object=1, frame=c(list(1)))"); + assertEval("substituteDirect(object=1, frame=list(c(list(1))))"); + assertEval("substituteDirect(object=1, frame=list(list(1)))"); + + assertEval("a<-substituteDirect(quote(x+1), NULL); a"); + assertEval("a<-substituteDirect(quote(x+1), NA); a"); + assertEval("a<-substituteDirect(quote(x+1), list(1)); a"); + assertEval("a<-substituteDirect(quote(x+1), list(x=1)); a"); + assertEval("a<-substituteDirect(quote(x+1), list(y=1)); a"); + assertEval("a<-substituteDirect(quote(x+1), c(list(x=1), 'breakme')); a"); + assertEval("a<-substituteDirect(quote(x+1), c(c(list(x=1)))); a"); + assertEval("a<-substituteDirect(quote(x+1), list(c(c(list(x=1))))); a"); + assertEval("a<-substituteDirect(quote(x+1), list(list(x=1))); a"); + assertEval("a<-substituteDirect(quote(x+1), c(list(x=1, 1))); a"); + assertEval("a<-substituteDirect(quote(x+y), c(list(x=1), list(y=1))); a"); + assertEval("substituteDirect(quote(x+1), frame=environment())"); + assertEval("f<-function() {}; substituteDirect(quote(x+1), frame=f)"); + assertEval("substituteDirect(quote(x+1), frame=setClass('a'))"); + + assertEval("substituteDirect(quote(x+1), list(x=1), cleanFunction=TRUE)"); + assertEval("substituteDirect(quote(x+1), list(x=1), cleanFunction=c(TRUE, 'breakme'))"); + assertEval("substituteDirect(quote(x+1), list(x=1), cleanFunction=c(c(TRUE, 'breakme')))"); + assertEval("substituteDirect(quote(x+1), list(x=1), cleanFunction=c(TRUE, FALSE))"); + assertEval("substituteDirect(quote(x+1), list(x=1), cleanFunction=list(c(TRUE), 'breakme'))"); + assertEval("substituteDirect(quote(x+1), list(x=1), cleanFunction=NA)"); + assertEval("substituteDirect(quote(x+1), list(x=1), cleanFunction=NULL)"); + assertEval("substituteDirect(quote(x+1), list(x=1), cleanFunction='a')"); + assertEval("substituteDirect(quote(x+1), list(x=1), cleanFunction=c('1'))"); + assertEval("substituteDirect(quote(x+1), list(x=1), cleanFunction=c(1))"); + assertEval("substituteDirect(quote(x+1), list(x=1), cleanFunction=environment())"); + } + +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestSplineFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestSplineFunctions.java new file mode 100644 index 0000000000..defaaa8812 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestSplineFunctions.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.test.library.stats; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestSplineFunctions extends TestBase { + + @Test + public void basicSplineCoef() { + // method "periodic" + assertEval(".Call(stats:::C_SplineCoef, 1, c(1), c(1))"); + assertEval(".Call(stats:::C_SplineCoef, 1, c(1:5), c(1:5))"); + assertEval(".Call(stats:::C_SplineCoef, 1, c(1:6), c(1:5, 1))"); + // method "natural" + assertEval(".Call(stats:::C_SplineCoef, 2, c(1), c(1))"); + assertEval(".Call(stats:::C_SplineCoef, 2, c(1:5), c(1:5))"); + // method "fmm" + assertEval(".Call(stats:::C_SplineCoef, 3, c(1:5), c(1:5))"); + // method "hyman" + assertEval(".Call(stats:::C_SplineCoef, 4, c(1:5), c(1:5))"); + + assertEval(".Call(stats:::C_SplineCoef, 0, c(1:5), c(1:5))"); + assertEval(".Call(stats:::C_SplineCoef, -1, c(1:5), c(1:5))"); + assertEval(".Call(stats:::C_SplineCoef, 111, c(1:5), c(1:5))"); + + assertEval(".Call(stats:::C_SplineCoef, NULL, c(1:5), c(1:5))"); + assertEval(".Call(stats:::C_SplineCoef, NA, c(1:5), c(1:5))"); + assertEval(".Call(stats:::C_SplineCoef, c(), c(1:5), c(1:5))"); + assertEval(".Call(stats:::C_SplineCoef, list(), c(1:5), c(1:5))"); + assertEval(".Call(stats:::C_SplineCoef, c(list()), c(1:5), c(1:5))"); + assertEval(Ignored.WrongCaller, ".Call(stats:::C_SplineCoef, 'abc', c(1:5), c(1:5))"); + assertEval(".Call(stats:::C_SplineCoef, c(1), c(1:5), c(1:5))"); + assertEval(".Call(stats:::C_SplineCoef, c(1, 2, 3), c(1), c(1))"); + assertEval(Ignored.WrongCaller, ".Call(stats:::C_SplineCoef, c('a'), c(1), c(1))"); + assertEval(Ignored.WrongCaller, ".Call(stats:::C_SplineCoef, list(1), c(1), c(1))"); + assertEval(Ignored.WrongCaller, ".Call(stats:::C_SplineCoef, environment(), c(1:5), c(1:5))"); + assertEval(Ignored.WrongCaller, ".Call(stats:::C_SplineCoef, function() {}, c(1:5), c(1:5))"); + assertEval(".Call(stats:::C_SplineCoef, 1, list(1), c(1))"); + assertEval(".Call(stats:::C_SplineCoef, 1, c(1), list(1))"); + + assertEval(".Call(stats:::C_SplineCoef, 1, NULL, c(1:5))"); + assertEval(".Call(stats:::C_SplineCoef, 1, NA, c(1:5))"); + assertEval(".Call(stats:::C_SplineCoef, 1, c(1:5), NULL)"); + assertEval(".Call(stats:::C_SplineCoef, 1, c(1:5), NA)"); + assertEval(".Call(stats:::C_SplineCoef, 1, NULL, NULL)"); + assertEval(".Call(stats:::C_SplineCoef, 1, NA, NA)"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java index 972ac0da24..2096f7059b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java @@ -58,4 +58,41 @@ public class TestTypeConvert extends TestBase { // UnsupportedSpecializationException: Unexpected values provided for ... assertEval(Ignored.Unimplemented, "type.convert('NA', 1)"); } + + @Test + public void typeConvertExternal2Test() { + assertEval(".External2(utils:::C_typeconvert, c('1'), 'NA', FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), 'NA', NA, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), 'NA', NULL, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), 'NA', 'TRUE', '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), 'NA', 'abc', '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), 'NA', list('abc'), '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), 'NA', list(), '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), 'NA', c(), '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), 'NA', c(NULL), '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), 'NA', 1, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), 'NA', 2, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), 'NA', environment(), '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), 'NA', function() {}, '.', 'allow.loss')"); + + assertEval(".External2(utils:::C_typeconvert, NULL, 'NA', FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, NA, 'NA', FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c(), 'NA', FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), NULL, FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), NA, FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), c(), FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c(1), c(1), FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c(1, TRUE), c(1), FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c(1, 'TRUE'), c(1), FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c(1, 'TRUE', 'x'), c(1), FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c(1, '1'), c(1), FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c(1, 'x'), c(1), FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), c(1), FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, list(1), list(1), FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, list('1'), list('1'), FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, list('1'), list(1), FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, environment(), 'NA', FALSE, '.', 'allow.loss')"); + assertEval(".External2(utils:::C_typeconvert, c('1'), environment(), FALSE, '.', 'allow.loss')"); + } + } diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py index e215042965..5e9c6ebfd3 100644 --- a/mx.fastr/mx_fastr.py +++ b/mx.fastr/mx_fastr.py @@ -407,7 +407,7 @@ def _test_subpackage(name): return '.'.join((_test_package(), name)) def _simple_generated_unit_tests(): - return ','.join(map(_test_subpackage, ['library.base', 'library.grid', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'S4', 'rng', 'runtime.data'])) + return ','.join(map(_test_subpackage, ['library.base', 'library.grid', 'library.methods', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'S4', 'rng', 'runtime.data'])) def _simple_unit_tests(): return ','.join([_simple_generated_unit_tests(), _test_subpackage('tck')]) -- GitLab