diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java index e10af96ef656029a47b577ff6008c194d61616d5..55a76080cb08370639afb5555aaf5e0a806f9f3f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java @@ -108,8 +108,9 @@ public abstract class Paste extends RBuiltinNode.Arg3 { protected RAbstractStringVector pasteListNullSep(VirtualFrame frame, RAbstractListVector values, String sep, @SuppressWarnings("unused") RNull collapse) { int length = lengthProfile.profile(values.getLength()); if (hasNonNullElements(values, length)) { - if (isStringSequence(values, length)) { - return createStringSequence(values, length, sep); + int seqPos = isStringSequence(values, length); + if (seqPos != -1) { + return createStringSequence(values, length, seqPos, sep); } else { String[] result = pasteListElements(frame, values, sep, length); if (result == ONE_EMPTY_STRING) { @@ -263,14 +264,25 @@ public abstract class Paste extends RBuiltinNode.Arg3 { } /** - * Tests for pattern = { stringScalar } intSequence. + * Tests for pattern = { scalar } intSequence { scalar }. */ - private static boolean isStringSequence(RAbstractListVector values, int length) { + private static int isStringSequence(RAbstractListVector values, int length) { int i = 0; + // consume prefix while (i < length && isScalar(values.getDataAt(i))) { i++; } - return i < length && values.getDataAt(i) instanceof RIntSequence; + if (i < length && values.getDataAt(i) instanceof RIntSequence) { + // consume suffix + int j = i + 1; + while (j < length && isScalar(values.getDataAt(j))) { + j++; + } + if (j == length) { + return i; + } + } + return -1; } private static boolean isScalar(Object dataAt) { @@ -278,14 +290,18 @@ public abstract class Paste extends RBuiltinNode.Arg3 { } @TruffleBoundary - private static RStringSequence createStringSequence(RAbstractListVector values, int length, String sep) { - assert isStringSequence(values, length); + private static RStringSequence createStringSequence(RAbstractListVector values, int length, int seqPos, String sep) { + assert isStringSequence(values, length) != -1; - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < values.getLength() - 1; i++) { - sb.append(values.getDataAt(i)).append(sep); + StringBuilder prefix = new StringBuilder(); + for (int i = 0; i < seqPos; i++) { + prefix.append(values.getDataAt(i)).append(sep); + } + RIntSequence seq = (RIntSequence) values.getDataAt(seqPos); + StringBuilder suffix = new StringBuilder(); + for (int i = seqPos + 1; i < length; i++) { + suffix.append(values.getDataAt(i)).append(sep); } - RIntSequence seq = (RIntSequence) values.getDataAt(length - 1); - return RDataFactory.createStringSequence(sb.toString(), seq.getStart(), seq.getStride(), seq.getLength()); + return RDataFactory.createStringSequence(prefix.toString(), suffix.toString(), seq.getStart(), seq.getStride(), seq.getLength()); } } 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 fbc36048a6d706b0cadd092ee1b28c79aae08a13..905a095769eedaf095117fe9c6d1fca0f2ee887f 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 @@ -273,8 +273,8 @@ public final class RDataFactory { return createStringVector(new String[]{RRuntime.STRING_NA}, false); } - public static RStringSequence createStringSequence(String template, int start, int stride, int length) { - return traceDataCreated(new RStringSequence(template, start, stride, length)); + public static RStringSequence createStringSequence(String prefix, String suffix, int start, int stride, int length) { + return traceDataCreated(new RStringSequence(prefix, suffix, start, stride, length)); } public static RComplexVector createEmptyComplexVector() { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringSequence.java index 588f4a9f58e3c4d3ae6d14d8c4ae3938e7104ca2..03c11fa316b416042f33958257930f2e024c2fee 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringSequence.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringSequence.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.runtime.data; +import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; @@ -34,13 +35,15 @@ public class RStringSequence extends RSequence implements RAbstractStringVector private final int start; private final int stride; - private final String template; + private final String prefix; + private final String suffix; - protected RStringSequence(String template, int start, int stride, int length) { + protected RStringSequence(String prefix, String suffix, int start, int stride, int length) { super(length); this.start = start; this.stride = stride; - this.template = template; + this.prefix = prefix != null ? prefix : ""; + this.suffix = suffix != null ? suffix : ""; } private static void resizeData(String[] newData, String[] data, int oldDataLength, String fill) { @@ -82,13 +85,13 @@ public class RStringSequence extends RSequence implements RAbstractStringVector @Override public String getDataAt(int index) { assert index >= 0 && index < getLength(); - return template + (start + stride * index); + return prefix + (start + stride * index) + suffix; } private void populateVectorData(String[] result) { int current = start; for (int i = 0; i < result.length && i < getLength(); i++) { - result[i] = template + current; + result[i] = prefix + current + suffix; current += stride; } } @@ -102,13 +105,17 @@ public class RStringSequence extends RSequence implements RAbstractStringVector return start; } + public int getEnd() { + return start + (getLength() - 1) * stride; + } + public int getStride() { return stride; } @Override public Object getStartObject() { - return template + start; + return prefix + start + suffix; } @Override @@ -132,4 +139,10 @@ public class RStringSequence extends RSequence implements RAbstractStringVector return null; } } + + @Override + public String toString() { + CompilerAsserts.neverPartOfCompilation(); + return "[\"" + getStartObject() + "\" - \"" + prefix + getEnd() + suffix + "\"]"; + } }