diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java index cb47c0ec4bff90da4adaa81fb71d0e52eecd23d0..5fbdec5c2d2a2baea2679a1195997b02473fe803 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java @@ -23,23 +23,20 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.RBuiltinKind.*; + import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.SlowPath; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.r.nodes.*; -import com.oracle.truffle.r.nodes.access.*; import com.oracle.truffle.r.nodes.builtin.*; -import com.oracle.truffle.r.nodes.builtin.RBuiltin.*; import com.oracle.truffle.r.nodes.unary.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; -@RBuiltin(name = "paste", kind = SUBSTITUTE, lastParameterKind = LastParameterKind.VAR_ARGS_SPECIALIZE) -// TODO INTERNAL +@RBuiltin(name = "paste", kind = INTERNAL) public abstract class Paste extends RBuiltinNode { - public abstract Object executeObject(VirtualFrame frame, Object value, String sep, Object collapse); + public abstract Object executeList(VirtualFrame frame, RList value, String sep, Object collapse); @Child CastStringNode castCharacterNode; @@ -64,125 +61,17 @@ public abstract class Paste extends RBuiltinNode { } } - private static final Object[] PARAMETER_NAMES = new Object[]{"...", "sep", "collapse"}; - - @Override - public Object[] getParameterNames() { - return PARAMETER_NAMES; - } - - @Override - public RNode[] getParameterValues() { - return new RNode[]{null, ConstantNode.create(" "), ConstantNode.create(RNull.instance)}; - } - - @Specialization - @SuppressWarnings("unused") - public RStringVector paste(RMissing value, Object sep, Object collapse) { - controlVisibility(); - return RDataFactory.createEmptyStringVector(); - } - - @Specialization - @SuppressWarnings("unused") - public RStringVector paste(RNull value, Object sep, Object collapse) { - controlVisibility(); - return RDataFactory.createEmptyStringVector(); - } - - @SuppressWarnings("unused") - @Specialization - @SlowPath - public String paste(int value, Object sep, Object collapse) { - controlVisibility(); - return String.valueOf(value); - } - - @SuppressWarnings("unused") - @Specialization - @SlowPath - public String paste(double value, Object sep, Object collapse) { - controlVisibility(); - return String.valueOf(value); - } - - @SuppressWarnings("unused") - @Specialization - public String paste(byte value, Object sep, Object collapse) { - controlVisibility(); - return RRuntime.logicalToString(value); - } - - @SuppressWarnings("unused") - @Specialization - public String paste(String value, Object sep, Object collapse) { - controlVisibility(); - return value; - } - - @SuppressWarnings("unused") - @Specialization - public String paste(RComplex value, Object sep, Object collapse) { - controlVisibility(); - return RRuntime.toString(value); - } - - @SuppressWarnings("unused") - @Specialization - public RStringVector paste(RStringVector vector, Object sep, Object collapse) { - controlVisibility(); - return checkCollapse(vector, collapse); - } - - @SuppressWarnings("unused") - @Specialization - public RStringVector paste(VirtualFrame frame, RIntVector vector, Object sep, Object collapse) { - controlVisibility(); - return checkCollapse(castCharacterVector(frame, vector), collapse); - } - - @SuppressWarnings("unused") - @Specialization - public RStringVector paste(VirtualFrame frame, RDoubleVector vector, Object sep, Object collapse) { - controlVisibility(); - return checkCollapse(castCharacterVector(frame, vector), collapse); - } - - @SuppressWarnings("unused") - @Specialization - public RStringVector paste(VirtualFrame frame, RIntSequence sequence, Object sep, Object collapse) { - controlVisibility(); - return checkCollapse(castCharacterVector(frame, sequence), collapse); - } - - @SuppressWarnings("unused") - @Specialization - public RStringVector paste(VirtualFrame frame, RDoubleSequence sequence, Object sep, Object collapse) { - controlVisibility(); - return checkCollapse(castCharacterVector(frame, sequence), collapse); - } - - @SuppressWarnings("unused") @Specialization - public RStringVector paste(VirtualFrame frame, RLogicalVector vector, Object sep, Object collapse) { + public RStringVector pasteList(VirtualFrame frame, RList values, String sep, Object collapse) { controlVisibility(); - return checkCollapse(castCharacterVector(frame, vector), collapse); - } - - @SuppressWarnings("unused") - @Specialization - public RStringVector paste(VirtualFrame frame, RList list, Object sep, Object collapse) { - controlVisibility(); - return checkCollapse(castCharacterVector(frame, list), collapse); - } - - @Specialization - public RStringVector paste(VirtualFrame frame, Object[] args, Object sep, Object collapse) { - controlVisibility(); - Object[] converted = new Object[args.length]; + if (isEmptyOrNull(values)) { + return RDataFactory.createEmptyStringVector(); + } + int length = values.getLength(); + Object[] converted = new Object[length]; int maxLength = 1; - for (int i = 0; i < args.length; i++) { - Object element = args[i]; + for (int i = 0; i < length; i++) { + Object element = values.getDataAt(i); if (element instanceof RVector || element instanceof RSequence) { converted[i] = castCharacterVector(frame, element); int len = ((RStringVector) converted[i]).getLength(); @@ -197,7 +86,7 @@ public abstract class Paste extends RBuiltinNode { String[] result = new String[maxLength]; for (int i = 0; i < maxLength; i++) { StringBuilder builder = new StringBuilder(); - for (int j = 0; j < args.length; j++) { + for (int j = 0; j < length; j++) { if (j != 0) { builder.append(sep); } @@ -214,13 +103,8 @@ public abstract class Paste extends RBuiltinNode { } } - private static RStringVector checkCollapse(RStringVector result, Object collapse) { - if (collapse != RNull.instance) { - String collapseString = RRuntime.toString(collapse); - return buildString(result, collapseString); - } else { - return result; - } + public boolean isEmptyOrNull(RList values) { + return values.getLength() == 0 || (values.getLength() == 1 && values.getDataAt(0) == RNull.instance); } private static RStringVector buildString(String[] value, String collapseString) { @@ -234,17 +118,6 @@ public abstract class Paste extends RBuiltinNode { return RDataFactory.createStringVector(new String[]{buildStringToString(sb)}, RDataFactory.COMPLETE_VECTOR); } - private static RStringVector buildString(RStringVector vector, String collapseString) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < vector.getLength(); i++) { - if (i > 0) { - sb.append(collapseString); - } - sb.append(vector.getDataAt(i)); - } - return RDataFactory.createStringVector(new String[]{buildStringToString(sb)}, RDataFactory.COMPLETE_VECTOR); - } - @SlowPath private static String buildStringToString(StringBuilder sb) { return sb.toString(); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java index 30f6b646bfc3bb76877723c4d2bf96c112dea7a7..f9002a7d65deb22c873c9735d48b01a486a14a23 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java @@ -28,40 +28,29 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.r.nodes.*; -import com.oracle.truffle.r.nodes.access.*; import com.oracle.truffle.r.nodes.builtin.*; -import com.oracle.truffle.r.nodes.builtin.RBuiltin.*; import com.oracle.truffle.r.runtime.data.*; -@RBuiltin(name = "paste0", kind = SUBSTITUTE, lastParameterKind = LastParameterKind.VAR_ARGS_SPECIALIZE) -// TODO INTERNAL +/** + * A straightforward implementation in terms of {@code paste} that doesn't attempt to be more + * efficient. + */ +@RBuiltin(name = "paste0", kind = INTERNAL) public abstract class Paste0 extends RBuiltinNode { @Child Paste pasteNode; - private Object paste(VirtualFrame frame, Object value, Object collapse) { + private Object paste(VirtualFrame frame, RList values, Object collapse) { if (pasteNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); pasteNode = insert(PasteFactory.create(new RNode[1], getBuiltin())); } - return pasteNode.executeObject(frame, value, "", collapse); - } - - private static final Object[] PARAMETER_NAMES = new Object[]{"...", "collapse"}; - - @Override - public Object[] getParameterNames() { - return PARAMETER_NAMES; - } - - @Override - public RNode[] getParameterValues() { - return new RNode[]{null, ConstantNode.create(RNull.instance)}; + return pasteNode.executeList(frame, values, "", collapse); } @Specialization - public Object paste0(VirtualFrame frame, Object value, Object collapse) { + public Object paste0(VirtualFrame frame, RList values, Object collapse) { controlVisibility(); - return paste(frame, value, collapse); + return paste(frame, values, collapse); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/R/paste.R b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/R/paste.R new file mode 100644 index 0000000000000000000000000000000000000000..45ea8c5ded41271208b740a31f2354f3d2f7c6cd --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/R/paste.R @@ -0,0 +1,33 @@ +# File src/library/base/R/paste.R +# Part of the R package, http://www.R-project.org +# +# Copyright (C) 1995-2012 The R Core Team +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# A copy of the GNU General Public License is available at +# http://www.r-project.org/Licenses/ + +paste <- function (..., sep = " ", collapse = NULL) + .Internal(paste(list(...), sep, collapse)) +paste0 <- function(..., collapse = NULL) + .Internal(paste0(list(...), collapse)) + +##=== Could we extend paste(.) to (optionally) accept a +## 2-vector for collapse ? With the following functionality + +##- paste.extra <- function(r, collapse=c(", "," and ")) { +##- n <- length(r) +##- if(n <= 1) paste(r) +##- else +##- paste(paste(r[-n],collapse=collapse[1L]), +##- r[n], sep=collapse[min(2,length(collapse))]) +##- }