diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java index 3172c03387b8c6831908e822d91b6c71b092811a..22d90022d232e769f4a9e8ef87d20f51fe1688cc 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java @@ -560,27 +560,37 @@ public class GrepFunctions { @TruffleBoundary protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, byte ignoreCaseL, byte perlL, byte fixedL, byte useBytesL) { controlVisibility(); - checkExtraArgs(RRuntime.LOGICAL_FALSE, perlL, fixedL, useBytesL, RRuntime.LOGICAL_FALSE); + checkExtraArgs(RRuntime.LOGICAL_FALSE, perlL, RRuntime.LOGICAL_FALSE, useBytesL, RRuntime.LOGICAL_FALSE); boolean ignoreCase = RRuntime.fromLogical(ignoreCaseL); String pattern = RegExp.checkPreDefinedClasses(patternArg.getDataAt(0)); int[] result = new int[vector.getLength()]; for (int i = 0; i < vector.getLength(); i++) { - result[i] = findIndex(pattern, vector.getDataAt(i), ignoreCase).get(0); + result[i] = findIndex(pattern, vector.getDataAt(i), ignoreCase, fixedL == RRuntime.LOGICAL_TRUE).get(0); } return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR); } - protected static List<Integer> findIndex(String pattern, String text, boolean ignoreCase) { - Matcher m = getPatternMatcher(pattern, text, ignoreCase); + protected static List<Integer> findIndex(String pattern, String text, boolean ignoreCase, boolean fixed) { List<Integer> list = new ArrayList<>(); - while (m.find()) { - // R starts counting at index 1 - list.add(m.start() + 1); - } - if (list.size() > 0) { - return list; + if (!fixed) { + int index; + if (ignoreCase) { + index = text.toLowerCase().indexOf(pattern.toLowerCase()); + } else { + index = text.indexOf(pattern); + } + list.add(index == -1 ? index : index + 1); + } else { + Matcher m = getPatternMatcher(pattern, text, ignoreCase); + while (m.find()) { + // R starts counting at index 1 + list.add(m.start() + 1); + } + if (list.size() > 0) { + return list; + } + list.add(-1); } - list.add(-1); return list; } @@ -603,7 +613,7 @@ public class GrepFunctions { String pattern = RegExp.checkPreDefinedClasses(patternArg.getDataAt(0)); Object[] result = new Object[vector.getLength()]; for (int i = 0; i < vector.getLength(); i++) { - int[] data = toIntArray(findIndex(pattern, vector.getDataAt(i), ignoreCase)); + int[] data = toIntArray(findIndex(pattern, vector.getDataAt(i), ignoreCase, true)); result[i] = RDataFactory.createIntVector(data, RDataFactory.COMPLETE_VECTOR); } return RDataFactory.createList(result); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java index 6c5026ec8c7faa4d1fb51eaa358c5652854d9e45..060d49b8bb18c11a6c150972d108efe13d2d1438 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java @@ -49,94 +49,67 @@ public abstract class Identical extends RBuiltinNode { private final ConditionProfile vecLengthProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile naArgsProfile = ConditionProfile.createBinaryProfile(); + @SuppressWarnings("unused") @Specialization(guards = "isRNull(x) || isRNull(y)") - protected byte doInternalIdentical(Object x, Object y, - // @formatter:off - @SuppressWarnings("unused") byte numEq, @SuppressWarnings("unused") byte singleNA, @SuppressWarnings("unused") byte attribAsSet, - @SuppressWarnings("unused") byte ignoreBytecode, @SuppressWarnings("unused") byte ignoreEnvironment) { - // @formatter:on + protected byte doInternalIdentical(Object x, Object y, byte numEq, byte singleNA, byte attribAsSet, byte ignoreBytecode, byte ignoreEnvironment) { controlVisibility(); return x == y ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE; } + @SuppressWarnings("unused") @Specialization - protected byte doInternalIdentical(byte x, byte y, - // @formatter:off - @SuppressWarnings("unused") byte numEq, @SuppressWarnings("unused") byte singleNA, @SuppressWarnings("unused") byte attribAsSet, - @SuppressWarnings("unused") byte ignoreBytecode, @SuppressWarnings("unused") byte ignoreEnvironment) { - // @formatter:on + protected byte doInternalIdentical(byte x, byte y, byte numEq, byte singleNA, byte attribAsSet, byte ignoreBytecode, byte ignoreEnvironment) { controlVisibility(); return x == y ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE; } + @SuppressWarnings("unused") @Specialization - protected byte doInternalIdentical(String x, String y, - // @formatter:off - @SuppressWarnings("unused") byte numEq, @SuppressWarnings("unused") byte singleNA, @SuppressWarnings("unused") byte attribAsSet, - @SuppressWarnings("unused") byte ignoreBytecode, @SuppressWarnings("unused") byte ignoreEnvironment) { - // @formatter:on + protected byte doInternalIdentical(String x, String y, byte numEq, byte singleNA, byte attribAsSet, byte ignoreBytecode, byte ignoreEnvironment) { controlVisibility(); return x.equals(y) ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE; } + @SuppressWarnings("unused") @Specialization - protected byte doInternalIdentical(double x, double y, - // @formatter:off - byte numEq, @SuppressWarnings("unused") byte singleNA, @SuppressWarnings("unused") byte attribAsSet, - @SuppressWarnings("unused") byte ignoreBytecode, @SuppressWarnings("unused") byte ignoreEnvironment) { - // @formatter:on + protected byte doInternalIdentical(double x, double y, byte numEq, byte singleNA, byte attribAsSet, byte ignoreBytecode, byte ignoreEnvironment) { controlVisibility(); boolean truth = numEq == RRuntime.LOGICAL_TRUE ? x == y : Double.doubleToRawLongBits(x) == Double.doubleToRawLongBits(y); return truth ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE; } + @SuppressWarnings("unused") @Specialization - protected byte doInternalIdentical(@SuppressWarnings("unused") RAbstractLogicalVector x, @SuppressWarnings("unused") REnvironment y, - // @formatter:off - @SuppressWarnings("unused") byte numEq, @SuppressWarnings("unused") byte singleNA, @SuppressWarnings("unused") byte attribAsSet, - @SuppressWarnings("unused") byte ignoreBytecode, @SuppressWarnings("unused") byte ignoreEnvironment) { - // @formatter:on + protected byte doInternalIdentical(RAbstractLogicalVector x, REnvironment y, byte numEq, byte singleNA, byte attribAsSet, byte ignoreBytecode, byte ignoreEnvironment) { controlVisibility(); return RRuntime.LOGICAL_FALSE; } + @SuppressWarnings("unused") @Specialization - protected byte doInternalIdentical(@SuppressWarnings("unused") REnvironment x, @SuppressWarnings("unused") RAbstractLogicalVector y, - // @formatter:off - @SuppressWarnings("unused") byte numEq, @SuppressWarnings("unused") byte singleNA, @SuppressWarnings("unused") byte attribAsSet, - @SuppressWarnings("unused") byte ignoreBytecode, @SuppressWarnings("unused") byte ignoreEnvironment) { - // @formatter:on + protected byte doInternalIdentical(REnvironment x, RAbstractLogicalVector y, byte numEq, byte singleNA, byte attribAsSet, byte ignoreBytecode, byte ignoreEnvironment) { controlVisibility(); return RRuntime.LOGICAL_FALSE; } + @SuppressWarnings("unused") @Specialization - protected byte doInternalIdentical(REnvironment x, REnvironment y, - // @formatter:off - @SuppressWarnings("unused") byte numEq, @SuppressWarnings("unused") byte singleNA, @SuppressWarnings("unused") byte attribAsSet, - @SuppressWarnings("unused") byte ignoreBytecode, @SuppressWarnings("unused") byte ignoreEnvironment) { - // @formatter:on + protected byte doInternalIdentical(REnvironment x, REnvironment y, byte numEq, byte singleNA, byte attribAsSet, byte ignoreBytecode, byte ignoreEnvironment) { controlVisibility(); // reference equality for environments return x == y ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE; } + @SuppressWarnings("unused") @Specialization - protected byte doInternalIdentical(RSymbol x, RSymbol y, - // @formatter:off - @SuppressWarnings("unused") byte numEq, @SuppressWarnings("unused") byte singleNA, @SuppressWarnings("unused") byte attribAsSet, - @SuppressWarnings("unused") byte ignoreBytecode, @SuppressWarnings("unused") byte ignoreEnvironment) { - // @formatter:on + protected byte doInternalIdentical(RSymbol x, RSymbol y, byte numEq, byte singleNA, byte attribAsSet, byte ignoreBytecode, byte ignoreEnvironment) { controlVisibility(); return x.getName().equals(y.getName()) ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE; } + @SuppressWarnings("unused") @Specialization - protected byte doInternalIdentical(@SuppressWarnings("unused") RLanguage x, @SuppressWarnings("unused") RLanguage y, - // @formatter:off - @SuppressWarnings("unused") byte numEq, @SuppressWarnings("unused") byte singleNA, @SuppressWarnings("unused") byte attribAsSet, - @SuppressWarnings("unused") byte ignoreBytecode, @SuppressWarnings("unused") byte ignoreEnvironment) { - // @formatter:on + protected byte doInternalIdentical(RLanguage x, RLanguage y, byte numEq, byte singleNA, byte attribAsSet, byte ignoreBytecode, byte ignoreEnvironment) { controlVisibility(); // TODO How to compare ASTs throw RError.nyi(this, "language objects not supported in 'identical'"); @@ -170,12 +143,9 @@ public abstract class Identical extends RBuiltinNode { return RRuntime.LOGICAL_FALSE; } + @SuppressWarnings("unused") @Specialization(guards = "!vectorsLists(x, y)") - protected byte doInternalIdenticalGeneric(RAbstractVector x, RAbstractVector y, - // @formatter:off - @SuppressWarnings("unused") byte numEq, @SuppressWarnings("unused") byte singleNA, @SuppressWarnings("unused") byte attribAsSet, - @SuppressWarnings("unused") byte ignoreBytecode, @SuppressWarnings("unused") byte ignoreEnvironment) { - // @formatter:on + protected byte doInternalIdenticalGeneric(RAbstractVector x, RAbstractVector y, byte numEq, byte singleNA, byte attribAsSet, byte ignoreBytecode, byte ignoreEnvironment) { controlVisibility(); if (vecLengthProfile.profile(x.getLength() != y.getLength())) { return RRuntime.LOGICAL_FALSE; @@ -189,12 +159,9 @@ public abstract class Identical extends RBuiltinNode { return RRuntime.LOGICAL_TRUE; } + @SuppressWarnings("unused") @Specialization - protected byte doInternalIdenticalGeneric(@SuppressWarnings("unused") RList x, @SuppressWarnings("unused") RList y, - // @formatter:off - @SuppressWarnings("unused") byte numEq, @SuppressWarnings("unused") byte singleNA, @SuppressWarnings("unused") byte attribAsSet, - @SuppressWarnings("unused") byte ignoreBytecode, @SuppressWarnings("unused") byte ignoreEnvironment) { - // @formatter:on + protected byte doInternalIdenticalGeneric(RList x, RList y, byte numEq, byte singleNA, byte attribAsSet, byte ignoreBytecode, byte ignoreEnvironment) { controlVisibility(); throw RError.nyi(this, "lists not supported in 'identical'"); } @@ -205,36 +172,38 @@ public abstract class Identical extends RBuiltinNode { return doInternalIdenticalGeneric(x.getVector(), y.getVector(), numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment); } + @SuppressWarnings("unused") @Specialization - protected byte doInternalIdenticalGeneric(@SuppressWarnings("unused") RFunction x, @SuppressWarnings("unused") RAbstractContainer y, - // @formatter:off - @SuppressWarnings("unused") Object numEq, @SuppressWarnings("unused") Object singleNA, @SuppressWarnings("unused") Object attribAsSet, - @SuppressWarnings("unused") Object ignoreBytecode, @SuppressWarnings("unused") Object ignoreEnvironment) { - // @formatter:on + protected byte doInternalIdenticalGeneric(RFunction x, RAbstractContainer y, Object numEq, Object singleNA, Object attribAsSet, Object ignoreBytecode, Object ignoreEnvironment) { controlVisibility(); return RRuntime.LOGICAL_FALSE; } + @SuppressWarnings("unused") @Specialization - protected byte doInternalIdenticalGeneric(@SuppressWarnings("unused") RLanguage x, @SuppressWarnings("unused") RAbstractContainer y, - // @formatter:off - @SuppressWarnings("unused") Object numEq, @SuppressWarnings("unused") Object singleNA, @SuppressWarnings("unused") Object attribAsSet, - @SuppressWarnings("unused") Object ignoreBytecode, @SuppressWarnings("unused") Object ignoreEnvironment) { - // @formatter:on + protected byte doInternalIdenticalGeneric(RLanguage x, RAbstractContainer y, Object numEq, Object singleNA, Object attribAsSet, Object ignoreBytecode, Object ignoreEnvironment) { controlVisibility(); return RRuntime.LOGICAL_FALSE; } + @SuppressWarnings("unused") @Specialization - protected byte doInternalIdenticalGeneric(@SuppressWarnings("unused") RAbstractContainer x, @SuppressWarnings("unused") RFunction y, - // @formatter:off - @SuppressWarnings("unused") Object numEq, @SuppressWarnings("unused") Object singleNA, @SuppressWarnings("unused") Object attribAsSet, - @SuppressWarnings("unused") Object ignoreBytecode, @SuppressWarnings("unused") Object ignoreEnvironment) { - // @formatter:on + protected byte doInternalIdenticalGeneric(RAbstractContainer x, RFunction y, Object numEq, Object singleNA, Object attribAsSet, Object ignoreBytecode, Object ignoreEnvironment) { controlVisibility(); return RRuntime.LOGICAL_FALSE; } + @SuppressWarnings("unused") + @Fallback + protected byte doInternalIdenticalWrongTypes(Object x, Object y, byte numEq, byte singleNA, byte attribAsSet, byte ignoreBytecode, byte ignoreEnvironment) { + controlVisibility(); + if (x.getClass() != y.getClass()) { + return RRuntime.LOGICAL_FALSE; + } else { + throw RInternalError.unimplemented(); + } + } + protected boolean vectorsLists(RAbstractVector x, RAbstractVector y) { return x instanceof RList && y instanceof RList; } 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 7d9fa7f80c3becfa9c006dfe57995ed7014af2dd..cbdc67d4663c7aa6229c65d69b3696ae16a67cb0 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 @@ -37906,6 +37906,42 @@ attr(,"match.length") attr(,"useBytes") [1] TRUE +##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testRegExpr +#{ regexpr("aaa", "bbbaaaccc", fixed=TRUE) } +[1] 4 +attr(,"match.length") +[1] 3 +attr(,"useBytes") +[1] TRUE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testRegExpr +#{ regexpr("aaa", c("bbbaaaccc", "haaah"), fixed=TRUE) } +[1] 4 2 +attr(,"match.length") +[1] 3 3 +attr(,"useBytes") +[1] TRUE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testRegExpr +#{ regexpr("aaa", c("bbbaaaccc", "hah"), fixed=TRUE) } +[1] 4 -1 +attr(,"match.length") +[1] 3 -1 +attr(,"useBytes") +[1] TRUE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testRegExpr +#{ x<-regexpr("aaa", "bbbaaaccc", fixed=TRUE); c(x[1]) } +[1] 4 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testRegExpr +#{ x<-regexpr("aaa", c("bbbaaaccc", "haaah"), fixed=TRUE); c(x[1], x[2]) } +[1] 4 2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testRegExpr +#{ x<-regexpr("aaa", c("bbbaaaccc", "hah"), fixed=TRUE); c(x[1], x[2]) } +[1] 4 -1 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_regexpr.testregexpr1 #argv <- list('package:', 'exNSS4', FALSE, FALSE, TRUE, FALSE); .Internal(regexpr(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]])) [1] -1 diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_regexpr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_regexpr.java index 4d526c20002f58ef120ca22f3d7509afb07ae14f..55610a73ca82e51112c92a97e2e2e2ecb1f9d7ad 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_regexpr.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_regexpr.java @@ -88,5 +88,14 @@ public class TestBuiltin_regexpr extends TestBase { assertEval(Ignored.Unknown, "regexpr(\"e\",c(\"arm\",\"foot\",\"lefroo\", \"bafoobar\"))"); // NOTE: this is without attributes assertEval(Ignored.Unknown, "regexpr(\"(a)[^a]\\\\1\", c(\"andrea apart\", \"amadeus\", NA))"); + + // FIXME: missing attributes + assertEval(Ignored.Unknown, "{ regexpr(\"aaa\", \"bbbaaaccc\", fixed=TRUE) }"); + assertEval(Ignored.Unknown, "{ regexpr(\"aaa\", c(\"bbbaaaccc\", \"haaah\"), fixed=TRUE) }"); + assertEval(Ignored.Unknown, "{ regexpr(\"aaa\", c(\"bbbaaaccc\", \"hah\"), fixed=TRUE) }"); + + assertEval("{ x<-regexpr(\"aaa\", \"bbbaaaccc\", fixed=TRUE); c(x[1]) }"); + assertEval("{ x<-regexpr(\"aaa\", c(\"bbbaaaccc\", \"haaah\"), fixed=TRUE); c(x[1], x[2]) }"); + assertEval("{ x<-regexpr(\"aaa\", c(\"bbbaaaccc\", \"hah\"), fixed=TRUE); c(x[1], x[2]) }"); } }