diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java index 552143bb828f91a3910d159cbbc903a59c4daf91..6d6a78006af8e0ccf810b925574b67d3e5e687b1 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -35,6 +35,7 @@ import com.oracle.truffle.r.library.fastrGrid.grDevices.DevHoldFlush; import com.oracle.truffle.r.library.fastrGrid.grDevices.DevOff; import com.oracle.truffle.r.library.fastrGrid.grDevices.DevSize; import com.oracle.truffle.r.library.fastrGrid.grDevices.InitWindowedDevice; +import com.oracle.truffle.r.library.fastrGrid.grDevices.PDF; import com.oracle.truffle.r.library.fastrGrid.grDevices.SavePlot; import com.oracle.truffle.r.library.fastrGrid.graphics.CPar; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; @@ -64,7 +65,7 @@ public final class FastRGridExternalLookup { case "devoff": return DevOff.create(); case "PDF": - return new IgnoredGridExternal(RNull.instance); + return new PDF(); case "devCairo": return new DevCairo(); default: diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/NullDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/NullDevice.java new file mode 100644 index 0000000000000000000000000000000000000000..0ce65bcc9666103b342352ab4e6fea0ef5d4365e --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/NullDevice.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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.library.fastrGrid.device; + +public class NullDevice implements GridDevice { + + @Override + public void openNewPage() { + } + + @Override + public void drawRect(DrawingContext ctx, double leftX, double bottomY, double width, double height, double rotationAnticlockWise) { + } + + @Override + public void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) { + } + + @Override + public void drawPolygon(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) { + } + + @Override + public void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius) { + } + + @Override + public void drawRaster(double leftX, double bottomY, double width, double height, int[] pixels, int pixelsColumnsCount, ImageInterpolation interpolation) { + } + + @Override + public void drawString(DrawingContext ctx, double leftX, double bottomY, double rotationAnticlockWise, String text) { + } + + @Override + public double getWidth() { + return 0; + } + + @Override + public double getHeight() { + return 0; + } + + @Override + public int getNativeWidth() { + return 0; + } + + @Override + public int getNativeHeight() { + return 0; + } + + @Override + public double getStringWidth(DrawingContext ctx, String text) { + return 0; + } + + @Override + public double getStringHeight(DrawingContext ctx, String text) { + return 0; + } + +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java index 371fe577b934023e585821fb963aaff0067f9172..872a98d181113df7a3837d2d39915b9ef23e7c60 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -24,6 +24,7 @@ package com.oracle.truffle.r.library.fastrGrid.grDevices; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.library.fastrGrid.GridContext; +import com.oracle.truffle.r.library.fastrGrid.device.NullDevice; import com.oracle.truffle.r.library.fastrGrid.device.SVGDevice; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.runtime.RError.Message; @@ -44,6 +45,11 @@ public class DevCairo extends RExternalBuiltinNode { } String filename = RRuntime.asString(args.getArgument(0)); + if (filename == null) { + GridContext.getContext().setCurrentDevice("null", new NullDevice()); + return RNull.instance; + } + int witdh = RRuntime.asInteger(args.getArgument(2)); int height = RRuntime.asInteger(args.getArgument(3)); if (RRuntime.isNA(witdh) || RRuntime.isNA(height) || RRuntime.isNA(filename) || filename.isEmpty()) { diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/PDF.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/PDF.java new file mode 100644 index 0000000000000000000000000000000000000000..78926da43b23d03a62785c91c0d5851589f32ba2 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/PDF.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018, 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.library.fastrGrid.grDevices; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.library.fastrGrid.GridContext; +import com.oracle.truffle.r.library.fastrGrid.device.NullDevice; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RNull; + +public class PDF extends RExternalBuiltinNode { + static { + Casts.noCasts(PDF.class); + } + + @Override + @TruffleBoundary + protected Object call(RArgsValuesAndNames args) { + if (args.getLength() < 1) { + throw error(Message.ARGUMENTS_REQUIRED_COUNT, args.getLength(), "PDF", 1); + } + + GridContext.getContext().setCurrentDevice("null", new NullDevice()); + RError.warning(this, RError.Message.GENERIC, "PDF device not supported. Using a dummy device."); + return RNull.instance; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R index f674261f52a3bb6ce12a93b23534fd86c567d2f5..f32979e54aedc0fd2a7082a71ffda161e7bea1e9 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R @@ -1,4 +1,4 @@ -# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2018, 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 @@ -68,7 +68,12 @@ eval(expression({ recordPlot <- function() { dl <- grid:::grid.Call(grid:::C_getDisplayList) dl.idx <- grid:::grid.Call(grid:::C_getDLindex) - list(dl = dl, dl.idx = dl.idx) + # The dummy elements and the class 'recordedplot' make the display list look + # like the GNUR one, which enables its use in the 'evaluate' package + # (used in knitr, for instance). + pl <- list(list(list("dummyCallX",list(list("dummyCallY")))), dl = dl, dl.idx = dl.idx) + class(pl) <- "recordedplot" + pl } # When replaying, the argument DL must be one produced by the overridden function recordPlot. diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java index f076d1a5e64fc162513b8369fe2d4d50108ec9d0..dad8d6b0fd1451bb70cca74236935405efa243d9 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -114,6 +114,9 @@ public final class CPar extends RExternalBuiltinNode { case "ylog": // TODO: return RDataFactory.createLogicalVectorFromScalar(false); + case "page": + // TODO: + return RDataFactory.createLogicalVectorFromScalar(false); default: if (!FastROptions.IgnoreGraphicsCalls.getBooleanValue()) { throw RError.nyi(RError.NO_CALLER, "C_Par parameter '" + name + "'"); diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h index 7cd01653107b217d3acc4cef2fdd5d7d27685406..aaf82384b184450d1e136097cbfa4b44f8dd95e1 100644 --- a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h +++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h @@ -1378,6 +1378,9 @@ SEXP Rf_asS4(SEXP x, Rboolean b, int i) { static SEXP R_tryEvalInternal(SEXP x, SEXP y, int *ErrorOccurred, int silent) { TRACE0(); + if (ErrorOccurred) { + *ErrorOccurred = 0; + } return ((call_R_tryEval) callbacks[R_tryEval_x])(x, y, ErrorOccurred, silent); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java index 2132fb8c92c6c75705e584d404c7253e9709ceac..dd35239badd6926d5752e2991c11e175a68fd6f6 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java @@ -170,6 +170,15 @@ public abstract class Bind extends RBaseNode { fromNotNullArgVector = vector; } if (emptyVectorProfile.profile(vector.getLength() == 0)) { + int[] dims = getVectorDimensions(vector); + int srcDim1Ind = type == BindType.cbind ? 0 : 1; + if (dims != null && dims[srcDim1Ind] > 0) { + // an empty matrix with a positive column, resp. row, dimension cannot be + // ignored + vectors[ind] = vector; + complete &= vector.isComplete(); + ind++; + } // nothing to do } else { vectors[ind] = vector; @@ -704,6 +713,9 @@ public abstract class Bind extends RBaseNode { boolean allRowDimNamesNull = true; int dstRowInd = 0; for (int i = 0; i < vectors.length; i++) { + if (firstDims[i] == 0) { + continue; + } RAbstractVector vec = vectorProfile.profile(vectors[i]); if (colDimResultNames == RNull.instance) { // get the first valid names value 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 eb61710d5e4fa123dbfb62a8b509f1215917d241..74c1128cc92dac05607e393db1f8ffcd5ede5c3c 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 @@ -345,7 +345,7 @@ public abstract class ConnectionFunctions { Casts casts = new Casts(TextConnection.class); CastsHelper.description(casts); casts.arg("text").allowNull().mustBe(stringValue()); - CastsHelper.open(casts).mustBe(equalTo("").or(equalTo("r").or(equalTo("w").or(equalTo("a")))), RError.Message.UNSUPPORTED_MODE); + CastsHelper.open(casts).mustBe(equalTo("").or(equalTo("r").or(equalTo("w").or(equalTo("a").or(equalTo("wr"))))), RError.Message.UNSUPPORTED_MODE); casts.arg("env").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class)); casts.arg("encoding").asIntegerVector().findFirst().mustNotBeNA(); } 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 2799b9c753295d5c511ebfbe90c87763da88e9bb..0925aa27d1f64b30e5e755d0ab023c34bd2508c1 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 @@ -5,7 +5,7 @@ * * Copyright (c) 1995-2015, The R Core Team * Copyright (c) 2003, The R Foundation - * Copyright (c) 2015, 2017, Oracle and/or its affiliates + * Copyright (c) 2015, 2018, Oracle and/or its affiliates * * All rights reserved. */ @@ -468,9 +468,10 @@ public class GrepFunctions { String value; if (fixed) { if (gsub) { - value = input.replace(pattern, replacement); + value = Pattern.compile(pattern, Pattern.LITERAL).matcher(input).replaceAll(replacement); } else { int ix = input.indexOf(pattern); + replacement = replacement.replace("\\\\", "\\"); value = ix < 0 ? input : input.substring(0, ix) + replacement + input.substring(ix + pattern.length()); } } else if (perl) { @@ -535,10 +536,11 @@ public class GrepFunctions { } else { replacement = convertGroups(replacement); + Matcher matcher = Pattern.compile(pattern, Pattern.DOTALL).matcher(input); if (gsub) { - value = input.replaceAll(pattern, replacement); + value = matcher.replaceAll(replacement); } else { - value = input.replaceFirst(pattern, replacement); + value = matcher.replaceFirst(replacement); } } result[i] = value; @@ -958,7 +960,7 @@ public class GrepFunctions { if (pattern.length() > 0 && pattern.charAt(0) == '*') { actualPattern = pattern.substring(1); } - return Pattern.compile(actualPattern, ignoreCase ? Pattern.CASE_INSENSITIVE : 0).matcher(text); + return Pattern.compile(actualPattern, Pattern.DOTALL | (ignoreCase ? Pattern.CASE_INSENSITIVE : 0)).matcher(text); } } @@ -1069,7 +1071,7 @@ public class GrepFunctions { @TruffleBoundary private static Matcher getPatternMatcher(String pattern, String text, boolean ignoreCase) { - return Pattern.compile(pattern, ignoreCase ? Pattern.CASE_INSENSITIVE : 0).matcher(text); + return Pattern.compile(pattern, Pattern.DOTALL | (ignoreCase ? Pattern.CASE_INSENSITIVE : 0)).matcher(text); } } 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 bf81f8a617cbe6c47303c4e6c100ffcd7d80de18..953d92bd68749e0dfa19d9e1cfac95283dac0dd9 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 @@ -31,8 +31,13 @@ import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Arrays; import java.util.EnumSet; +import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; @@ -59,9 +64,11 @@ import com.oracle.truffle.r.runtime.context.Engine.ParseException; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.REmpty; import com.oracle.truffle.r.runtime.data.RExpression; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RLanguage; +import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @@ -286,13 +293,53 @@ public abstract class Parse extends RBuiltinNode.Arg6 { /** * This class aspires to reconstruct the original parse tree through visiting a parsed - * expression(s). - * - * The current implementation does not reconstruct the parse tree completely. Instead, it deals - * with symbols only (i.e. a flat tree is produced), which should suffice for templating - * packages, such as knitr. + * expression(s). The reconstruction cannot be done completely as some information is lost, but + * the result should suffice for templating packages, such as knitr. */ - static class ParseDataVisitor extends RSyntaxVisitor<Object> { + static class ParseDataVisitor extends RSyntaxVisitor<ParseDataVisitor.OctetNode> { + + static class OctetNode { + static final List<OctetNode> NO_CHILDREN = java.util.Collections.emptyList(); + + final int id; + final int startLine; + final int startColumn; + final int endLine; + final int endColumn; + final TokenType tokenType; + final String txt; + final List<OctetNode> children; + + OctetNode(int id, int startLine, int startColumn, int endLine, int endColumn, TokenType tokenType, String txt, List<OctetNode> children) { + this.id = id; + this.startLine = startLine; + this.startColumn = startColumn; + this.endLine = endLine; + this.endColumn = endColumn; + this.tokenType = tokenType; + this.txt = txt; + this.children = children; + } + + void store(ParseDataVisitor vis, int parentId) { + for (OctetNode child : children) { + child.store(vis, id); + } + + vis.data.add(startLine); + vis.data.add(startColumn); + vis.data.add(endLine); + vis.data.add(endColumn); + vis.data.add(tokenType.terminal ? 1 : 0); + vis.data.add(tokenType.code); + vis.data.add(id); + vis.data.add(parentId); + + vis.tokens.add(tokenType.tokenName); + vis.text.add(txt); + } + + } private final RExpression exprs; @@ -322,64 +369,115 @@ public abstract class Parse extends RBuiltinNode.Arg6 { * This enum mimics the <code>yytokentype</code> enum from <code>src/main/gram.c</code>. */ enum TokenType { + expr(77, false), + IF(272, true, "if"), + WHILE(274, true, "while"), + FOR(270, true, "for"), + IN(271, true, "in"), + BREAK(276, true, "break"), + REPEAT(277, true, "repeat"), + NEXT(275, true, "next"), + LEFT_ASSIGN(266, true, "<-"), + EQ_ASSIGN(267, true, "="), + RIGHT_ASSIGN(268, true, "->"), + PLUS(43, true, "+", true, true), + MINUS(45, true, "-", true, true), + MULT(42, true, "*", true, true), + DIV(47, true, "/", true, true), + POW(94, true, "^", true, true), + DOLLAR(36, true, "$", true, true), + AT(64, true, "@", true, true), + COLON(58, true, ":", true, true), + QUESTION(63, true, "?", true, false), + TILDE(126, true, "~", true, false), + EXCLAMATION(33, true, "!", true, false), + GT(278, true, ">"), + GE(279, true, ">="), + LT(280, true, "<"), + LE(281, true, "<="), + EQ(282, true, "=="), + NE(283, true, "!="), + AND(284, true, "&"), + AND2(286, true, "&&"), + OR(285, true, "|"), + OR2(287, true, "||"), SYMBOL(263, true), SYMBOL_FUNCTION_CALL(296, true), - SPECIAL(304, true); + SPECIAL(304, true), + NULL_CONST(262, true), + NUM_CONST(261, true), + STR_CONST(260, true), + FUNCTION(264, true), + LPAREN(40, true, "(", true, false), + RPAREN(41, true, ")", true, false); final int code; final boolean terminal; + final String symbol; + final String tokenName; + final boolean infix; - TokenType(int c, boolean term) { + TokenType(int c, boolean term, String symbol, boolean useSymbolAsTokenName, boolean infix) { this.code = c; this.terminal = term; + this.symbol = symbol; + this.tokenName = useSymbolAsTokenName ? "'" + symbol + "'" : name(); + this.infix = infix; } - } - private void addOctet(RSyntaxElement element, TokenType tokenType, String txt) { - addOctet(element.getSourceSection().getStartLine(), element.getSourceSection().getStartColumn(), element.getSourceSection().getEndLine(), element.getSourceSection().getEndColumn(), - tokenType, txt); - } + TokenType(int c, boolean term, String symbol) { + this(c, term, symbol, false, false); + } - private void addOctet(RSymbol symbol) { - addOctet(RRuntime.INT_NA, RRuntime.INT_NA, RRuntime.INT_NA, RRuntime.INT_NA, TokenType.SYMBOL, symbol.getName()); - containsNA = true; + TokenType(int c, boolean term) { + this(c, term, null, false, false); + } + + String getSymbol() { + return symbol; + } } - private void addOctet(int startLine, int startColumn, int endLine, int endColumn, TokenType tokenType, String txt) { - // TODO: adjust the parentId correctly - int parentId = 0; + private static final Map<String, TokenType> FUNCTION_TOKENS = Arrays.stream(TokenType.values()).filter(tt -> tt.symbol != null).collect( + Collectors.toMap(TokenType::getSymbol, Function.identity())); - data.add(startLine); - data.add(startColumn); - data.add(endLine); - data.add(endColumn); - data.add(tokenType.terminal ? 1 : 0); - data.add(tokenType.code); - data.add(idCounter); - data.add(parentId); + private OctetNode newOctet(RSyntaxElement element, TokenType tokenType, String txt, List<OctetNode> children) { + return newOctet(element.getSourceSection().getStartLine(), element.getSourceSection().getStartColumn(), element.getSourceSection().getEndLine(), element.getSourceSection().getEndColumn(), + tokenType, txt, children); + } - tokens.add(tokenType.name()); - text.add(txt); + private OctetNode newOctet(RSymbol symbol, List<OctetNode> children) { + OctetNode octet = newOctet(RRuntime.INT_NA, RRuntime.INT_NA, RRuntime.INT_NA, RRuntime.INT_NA, TokenType.SYMBOL, symbol.getName(), children); + containsNA = true; + return octet; + } - idCounter++; + private OctetNode newOctet(int startLine, int startColumn, int endLine, int endColumn, TokenType tokenType, String txt, List<OctetNode> children) { + return new OctetNode(++idCounter, startLine, startColumn, endLine, endColumn, tokenType, txt, children); } @TruffleBoundary RIntVector getParseData() { int exprLen = exprs.getLength(); + List<OctetNode> rootOctets = new ArrayList<>(); for (int i = 0; i < exprLen; i++) { Object x = exprs.getDataAt(i); if (x instanceof RLanguage) { RBaseNode rep = ((RLanguage) x).getRep(); assert rep instanceof RSyntaxElement; - accept((RSyntaxElement) rep); + rootOctets.add(accept((RSyntaxElement) rep)); } else if (x instanceof RSymbol) { - addOctet((RSymbol) x); + rootOctets.add(newOctet((RSymbol) x, OctetNode.NO_CHILDREN)); } else { // TODO: primitives } } + // Store the octet tree to the corresponding vectors + for (OctetNode rootOctet : rootOctets) { + rootOctet.store(this, 0); + } + int[] dataArray = new int[data.size()]; for (int i = 0; i < dataArray.length; i++) { dataArray[i] = data.get(i); @@ -396,56 +494,98 @@ public abstract class Parse extends RBuiltinNode.Arg6 { tokensArray[i] = tokens.get(i); } - parseData.setAttr("text", RDataFactory.createStringVector(textArray, true)); parseData.setAttr("tokens", RDataFactory.createStringVector(tokensArray, true)); + parseData.setAttr("text", RDataFactory.createStringVector(textArray, true)); parseData.setClassAttr(RDataFactory.createStringVector("parseData")); parseData.setDimensions(new int[]{8, idCounter}); + return parseData; } @Override - protected Object visit(RSyntaxCall element) { + protected OctetNode visit(RSyntaxCall element) { + LinkedList<OctetNode> children = new LinkedList<>(); + RSyntaxElement lhs = element.getSyntaxLHS(); - if (lhs instanceof RSyntaxLookup) { + if (lhs instanceof RSyntaxCall) { + children.add(accept(lhs)); + children.addAll(visitArguments(element, 0, Integer.MAX_VALUE)); + } else if (lhs instanceof RSyntaxLookup) { String symbol = ((RSyntaxLookup) lhs).getIdentifier(); RDeparse.Func func = RDeparse.getFunc(symbol); - if (func == null) { - addOctet(element, TokenType.SYMBOL_FUNCTION_CALL, symbol); + TokenType tt = null; + if (func != null) { + tt = FUNCTION_TOKENS.get(symbol); + } + if (tt == null) { + tt = TokenType.SYMBOL_FUNCTION_CALL; + } + if (tt.infix) { + children.addAll(visitArguments(element, 0, 1)); + children.add(newOctet(lhs, tt, symbol, OctetNode.NO_CHILDREN)); + children.addAll(visitArguments(element, 1, 2)); + } else { + children.add(newOctet(lhs, tt, symbol, OctetNode.NO_CHILDREN)); + children.addAll(visitArguments(element, 0, Integer.MAX_VALUE)); + } + if (tt == TokenType.LPAREN) { + OctetNode lastChild = children.getLast(); + children.add(new OctetNode(++idCounter, lastChild.endLine, lastChild.endColumn + 1, lastChild.endLine, lastChild.endColumn + 1, TokenType.RPAREN, ")", OctetNode.NO_CHILDREN)); } } + return newOctet(element, TokenType.expr, "", children); + } + + private List<OctetNode> visitArguments(RSyntaxCall element, int from, int to) { + List<OctetNode> children = new ArrayList<>(); RSyntaxElement[] args = element.getSyntaxArguments(); - for (int i = 0; i < args.length; i++) { - accept(args[i]); + for (int i = from; i < Math.min(args.length, to); i++) { + OctetNode argOctet = accept(args[i]); + if (argOctet != null) { + children.add(argOctet); + } } - - return null; + return children; } @Override - protected Object visit(RSyntaxConstant element) { - // TODO: recognize constants - return null; + protected OctetNode visit(RSyntaxConstant element) { + TokenType tt; + Object value = element.getValue(); + if (value == RNull.instance) { + tt = TokenType.NULL_CONST; + } else if (value instanceof Number) { + tt = TokenType.NUM_CONST; + } else if (value instanceof String) { + tt = TokenType.STR_CONST; + } else if (value == REmpty.instance || value == RMissing.instance) { + return null; // ignored + } else { + throw RInternalError.shouldNotReachHere("Unknown RSyntaxConstant in ParseDataVisitor " + (value == null ? "null" : value.getClass().getSimpleName())); + } + + OctetNode constChild = newOctet(element, tt, element.getSourceSection().getCharacters().toString(), OctetNode.NO_CHILDREN); + return newOctet(element, TokenType.expr, "", java.util.Collections.singletonList(constChild)); } @Override - protected Object visit(RSyntaxLookup element) { + protected OctetNode visit(RSyntaxLookup element) { String symbol = element.getIdentifier(); - addOctet(element, TokenType.SYMBOL, symbol); - return null; + return newOctet(element, TokenType.SYMBOL, symbol, OctetNode.NO_CHILDREN); } @Override - protected Object visit(RSyntaxFunction element) { + protected OctetNode visit(RSyntaxFunction element) { + List<OctetNode> children = new ArrayList<>(); for (RSyntaxElement arg : element.getSyntaxArgumentDefaults()) { if (arg != null) { - accept(arg); + children.add(accept(arg)); } } - accept(element.getSyntaxBody()); - - return null; + children.add(accept(element.getSyntaxBody())); + return newOctet(element, TokenType.FUNCTION, "function", children); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java index ebd98fae25d107759455ac237a1670fb0236b499..52c05fa2eda814358fd124fc27d01cb885fcb343 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java @@ -47,6 +47,7 @@ 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.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -175,6 +176,22 @@ public abstract class Sprintf extends RBuiltinNode.Arg2 { return RDataFactory.createStringVector(r, RDataFactory.COMPLETE_VECTOR); } + @Specialization(guards = "fmtLengthOne(fmt)") + @TruffleBoundary + protected RStringVector sprintf(RAbstractStringVector fmt, RAbstractLogicalVector x) { + return sprintf(fmt.getDataAt(0), x); + } + + @Specialization + @TruffleBoundary + protected RStringVector sprintf(String fmt, RAbstractLogicalVector x) { + String[] r = new String[x.getLength()]; + for (int k = 0; k < r.length; k++) { + r[k] = format(fmt, x.getDataAt(k)); + } + return RDataFactory.createStringVector(r, RDataFactory.COMPLETE_VECTOR); + } + @Specialization(guards = "fmtLengthOne(fmt)") @TruffleBoundary protected RStringVector sprintf(RAbstractStringVector fmt, RAbstractStringVector x) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java index d60b9779df596070a35d174b733b3aeecdf37d55..5bbff2e39bac2b7d38b8bdcbdbac458a4326b703 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java @@ -222,7 +222,7 @@ public class ConnectionSupport { enum AbstractOpenMode { Lazy(new String[]{""}, true, true, true), Read(new String[]{"r", "rt"}, true, true, false), - Write(new String[]{"w", "wt"}, true, false, true), + Write(new String[]{"w", "wt", "wr"}, true, false, true), Append(new String[]{"a", "at"}, true, false, true), ReadBinary(new String[]{"rb"}, false, true, false), WriteBinary(new String[]{"wb"}, false, false, true), 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 d606d1ca45d80460b2e8e0e214d2926d37694371..8ad6b28bbead4b239ae670cd2e29eabd6202b81f 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 @@ -13755,6 +13755,15 @@ c 2 b 1 c 2 +##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testCbind# +#{ cbind(integer(0), NULL, matrix(integer(0),0,1)) } + [,1] [,2] [,3] + +##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testCbind# +#{ cbind(integer(0), NULL, matrix(integer(0),1,0)) } + +[1,] + ##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testCbind# #{ cbind(list(1,2), TRUE, "a") } [,1] [,2] [,3] @@ -29082,6 +29091,14 @@ integer(0) #{ .Internal(grepl("7", 7, F, F, F, F, F, F)) } Error: invalid 'text' argument +##com.oracle.truffle.r.test.builtins.TestBuiltin_grepl.testGrepl# +#{ .Internal(grepl('.+X', 'a<<<NEWLINE>>>Xb', F, F, F, F, F, F)) } +[1] TRUE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_grepl.testGrepl# +#{ .Internal(grepl('.+X', 'a<<<NEWLINE>>>Xb', F, F, T, F, F, F)) } +[1] FALSE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_grepl.testGrepl# #{ .Internal(grepl(7, "7", F, F, F, F, F, F)) } Error: invalid 'pattern' argument @@ -29216,6 +29233,18 @@ In gsub("a", "aa", "prAgue alley", fixed = TRUE, ignore.case = TRUE) : #{ gsub("h","", c("hello", "hi", "bye"), fixed=TRUE) } [1] "ello" "i" "bye" +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub# +#{ gsub('.*X', '', 'a<<<NEWLINE>>>Xb', perl = FALSE) } +[1] "b" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub# +#{ gsub('.*X', '', 'a<<<NEWLINE>>>Xb', perl = TRUE) } +[1] "a\nb" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub# +#{ gsub('~', '\\\\X', '~') } +[1] "\\X" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub# #{ gsub(pattern = 'a*', replacement = 'x', x = 'ÄaaaaÄ', perl = TRUE) } [1] "xÄxÄx" @@ -48241,39 +48270,56 @@ expression(NULL) expression(expr1) ##com.oracle.truffle.r.test.builtins.TestBuiltin_parse.testParseData# -#if (!any(R.version$engine == "FastR")) { structure(c(1L, 1L, 1L, 1L, 1L, 263L, 0L, 0L), text = "x", tokens = "SYMBOL", class = "parseData", .Dim = c(8L, 1L)) } else { p <- parse(text = 'x = 1', keep.source = TRUE); attr(p, 'srcfile')$parseData } - [,1] -[1,] 1 -[2,] 1 -[3,] 1 -[4,] 1 -[5,] 1 -[6,] 263 -[7,] 0 -[8,] 0 -attr(,"text") -[1] "x" +#if (!any(R.version$engine == "FastR")) { structure(c(1L, 3L, 1L, 3L, 1L, 267L, 1L, 5L, 1L, 1L, 1L, 1L, 1L, 263L, 2L, 5L, 1L, 5L, 1L, 5L, 1L, 261L, 3L, 4L, 1L, 5L, 1L, 5L, 0L, 77L, 4L, 5L, 1L, 1L, 1L, 5L, 0L, 77L, 5L, 0L), tokens = c("EQ_ASSIGN", "SYMBOL", "NUM_CONST", "expr", "expr"), text = c("=", "x", "1", "", ""), class = "parseData", .Dim = c(8L, 5L)) } else { p <- parse(text = 'x = 1', keep.source = TRUE); attr(p, 'srcfile')$parseData } + [,1] [,2] [,3] [,4] [,5] +[1,] 1 1 1 1 1 +[2,] 3 1 5 5 1 +[3,] 1 1 1 1 1 +[4,] 3 1 5 5 5 +[5,] 1 1 1 0 0 +[6,] 267 263 261 77 77 +[7,] 1 2 3 4 5 +[8,] 5 5 4 5 0 attr(,"tokens") -[1] "SYMBOL" +[1] "EQ_ASSIGN" "SYMBOL" "NUM_CONST" "expr" "expr" +attr(,"text") +[1] "=" "x" "1" "" "" attr(,"class") [1] "parseData" ##com.oracle.truffle.r.test.builtins.TestBuiltin_parse.testParseData# -#if (!any(R.version$engine == "FastR")) { structure(c(1L, 1L, 1L, 1L, 1L, 263L, 0L, 0L, 1L, 5L, 1L, 5L, 1L, 263L, 1L, 0L, 1L, 12L, 1L, 28L, 1L, 296L, 2L, 0L, 1L, 27L, 1L, 27L, 1L, 263L, 3L, 0L, 1L, 31L, 1L, 32L, 1L, 263L, 4L, 0L, 1L, 51L, 1L, 51L, 1L, 263L, 5L, 0L), text = c("x", "x", "rnorm", "z", "f2", "a"), tokens = c("SYMBOL", "SYMBOL", "SYMBOL_FUNCTION_CALL", "SYMBOL", "SYMBOL", "SYMBOL"), class = "parseData", .Dim = c(8L, 6L)) } else { p <- parse(text = 'x = x + 1; rnorm(1, std = z); f2 <- function(a=1) a', keep.source = TRUE); attr(p, 'srcfile')$parseData } - [,1] [,2] [,3] [,4] [,5] [,6] -[1,] 1 1 1 1 1 1 -[2,] 1 5 12 27 31 51 -[3,] 1 1 1 1 1 1 -[4,] 1 5 28 27 32 51 -[5,] 1 1 1 1 1 1 -[6,] 263 263 296 263 263 263 -[7,] 0 1 2 3 4 5 -[8,] 0 0 0 0 0 0 -attr(,"text") -[1] "x" "x" "rnorm" "z" "f2" "a" +#if (!any(R.version$engine == "FastR")) { structure(c(1L, 3L, 1L, 3L, 1L, 267L, 1L, 8L, 1L, 1L, 1L, 1L, 1L, 263L, 2L, 8L, 1L, 5L, 1L, 5L, 1L, 263L, 3L, 7L, 1L, 7L, 1L, 7L, 1L, 43L, 4L, 7L, 1L, 9L, 1L, 9L, 1L, 261L, 5L, 6L, 1L, 9L, 1L, 9L, 0L, 77L, 6L, 7L, 1L, 5L, 1L, 9L, 0L, 77L, 7L, 8L, 1L, 1L, 1L, 9L, 0L, 77L, 8L, 0L, 1L, 12L, 1L, 16L, 1L, 296L, 9L, 13L, 1L, 18L, 1L, 18L, 1L, 261L, 10L, 11L, 1L, 18L, 1L, 18L, 0L, 77L, 11L, 13L, 1L, 27L, 1L, 27L, 1L, 263L, 12L, 13L, 1L, 12L, 1L, 28L, 0L, 77L, 13L, 0L, 1L, 34L, 1L, 35L, 1L, 266L, 14L, 20L, 1L, 31L, 1L, 32L, 1L, 263L, 15L, 20L, 1L, 48L, 1L, 48L, 1L, 261L, 16L, 17L, 1L, 48L, 1L, 48L, 0L, 77L, 17L, 19L, 1L, 51L, 1L, 51L, 1L, 263L, 18L, 19L, 1L, 37L, 1L, 51L, 1L, 264L, 19L, 20L, 1L, 31L, 1L, 51L, 0L, 77L, 20L, 0L), tokens = c("EQ_ASSIGN", "SYMBOL", "SYMBOL", "'+'", "NUM_CONST", "expr", "expr", "expr", "SYMBOL_FUNCTION_CALL", "NUM_CONST", "expr", "SYMBOL", "expr", "LEFT_ASSIGN", "SYMBOL", "NUM_CONST", "expr", "SYMBOL", "FUNCTION", "expr"), text = c("=", "x", "x", "+", "1", "", "", "", "rnorm", "1", "", "z", "", "<-", "f2", "1", "", "a", "function", ""), class = "parseData", .Dim = c(8L, 20L)) } else { p <- parse(text = 'x = x + 1; rnorm(1, std = z); f2 <- function(a=1) a', keep.source = TRUE); attr(p, 'srcfile')$parseData } + [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] +[1,] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +[2,] 3 1 5 7 9 9 5 1 12 18 18 27 12 34 +[3,] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +[4,] 3 1 5 7 9 9 9 9 16 18 18 27 28 35 +[5,] 1 1 1 1 1 0 0 0 1 1 0 1 0 1 +[6,] 267 263 263 43 261 77 77 77 296 261 77 263 77 266 +[7,] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 +[8,] 8 8 7 7 6 7 8 0 13 11 13 13 0 20 + [,15] [,16] [,17] [,18] [,19] [,20] +[1,] 1 1 1 1 1 1 +[2,] 31 48 48 51 37 31 +[3,] 1 1 1 1 1 1 +[4,] 32 48 48 51 51 51 +[5,] 1 1 0 1 1 0 +[6,] 263 261 77 263 264 77 +[7,] 15 16 17 18 19 20 +[8,] 20 17 19 19 20 0 attr(,"tokens") -[1] "SYMBOL" "SYMBOL" "SYMBOL_FUNCTION_CALL" -[4] "SYMBOL" "SYMBOL" "SYMBOL" + [1] "EQ_ASSIGN" "SYMBOL" "SYMBOL" + [4] "'+'" "NUM_CONST" "expr" + [7] "expr" "expr" "SYMBOL_FUNCTION_CALL" +[10] "NUM_CONST" "expr" "SYMBOL" +[13] "expr" "LEFT_ASSIGN" "SYMBOL" +[16] "NUM_CONST" "expr" "SYMBOL" +[19] "FUNCTION" "expr" +attr(,"text") + [1] "=" "x" "x" "+" "1" "" + [7] "" "" "rnorm" "1" "" "z" +[13] "" "<-" "f2" "1" "" "a" +[19] "function" "" attr(,"class") [1] "parseData" @@ -51770,6 +51816,22 @@ b 3 4 b c [1,] 1 2 +##com.oracle.truffle.r.test.builtins.TestBuiltin_rbind.testRbind# +#{ rbind(integer(0), NULL, matrix(integer(0),0,1)) } + [,1] + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rbind.testRbind# +#{ rbind(integer(0), NULL, matrix(integer(0),1,0)) } + +[1,] +[2,] +[3,] + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rbind.testRbind# +#{ rbind(logical(0),matrix(character(0),0,0)) } + +[1,] + ##com.oracle.truffle.r.test.builtins.TestBuiltin_rbind.testRbind# #{ rbind(matrix(1:4, nrow=2), z=c(m=8,n=9)) } m n @@ -72120,6 +72182,10 @@ Error: invalid 'pattern' argument #{ sub('^[[:space:]]*(.*)', '\\1', 'R (>= 3.0.3)') } [1] "R (>= 3.0.3)" +##com.oracle.truffle.r.test.builtins.TestBuiltin_sub.testSub# +#{ sub('~', '\\\\X', '~') } +[1] "\\X" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_sub.testSub# #{ sub(pattern = 'a*', replacement = 'x', x = 'ÄaaaaÄ', perl = TRUE) } [1] "xÄaaaaÄ" diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java index 81f4608d39ae4e2164a607bf9846dc2c753c772c..3f40e8a74cc168c016e666380a75bcd749cdfb79 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java @@ -91,6 +91,9 @@ public class TestBuiltin_cbind extends TestBase { assertEval("{ cbind(2,3, c(1,1,1)) }"); assertEval("{ cbind(2.1:10,32.2) }"); + assertEval("{ cbind(integer(0), NULL, matrix(integer(0),0,1)) }"); + assertEval("{ cbind(integer(0), NULL, matrix(integer(0),1,0)) }"); + assertEval("{ x<-list(a=7, b=NULL, c=42); y<-as.data.frame(do.call(cbind,x)); y }"); // Note: CachedExtractVectorNode replaces vector 'a', 'b', with a scalar 'b', which caused diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grepl.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grepl.java index 1e2e74500566da9a3ca4116c2d461072c978c3dc..c2875465a19c225ab16d28dd1e4df50f45b37b33 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grepl.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grepl.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2018, Oracle and/or its affiliates * * All rights reserved. */ @@ -79,5 +79,9 @@ public class TestBuiltin_grepl extends TestBase { assertEval("{ .Internal(grepl(7, \"7\", F, F, F, F, F, F)) }"); assertEval("{ .Internal(grepl(character(), \"7\", F, F, F, F, F, F)) }"); assertEval("{ .Internal(grepl(\"7\", 7, F, F, F, F, F, F)) }"); + // the dot does not match the new line in a non-Perl regexp + assertEval("{ .Internal(grepl('.+X', 'a\nXb', F, F, F, F, F, F)) }"); + // the dot matches the new line in a Perl regexp + assertEval("{ .Internal(grepl('.+X', 'a\nXb', F, F, T, F, F, F)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java index 05e8cbecd2e5d7d4cf71e6785fb3ed0811b8eb77..69f01ee11f09832b4337134c45d2ba7970fa3cb5 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2017, Oracle and/or its affiliates + * Copyright (c) 2013, 2018, Oracle and/or its affiliates * * All rights reserved. */ @@ -200,6 +200,13 @@ public class TestBuiltin_gsub extends TestBase { assertEval("{ gsub(pattern = 'a*', replacement = 'x', x = 'ÄaÄ', perl = TRUE) }"); assertEval("{ gsub(pattern = 'a*', replacement = 'x', x = 'ÄaaaaÄ', perl = TRUE) }"); + // the dot does not match the new line in a non-Perl regexp + assertEval("{ gsub('.*X', '', 'a\nXb', perl = FALSE) }"); + // the dot matches the new line in a Perl regexp + assertEval("{ gsub('.*X', '', 'a\nXb', perl = TRUE) }"); + + assertEval("{ gsub('~', '\\\\\\\\X', '~') }"); + // Expected output: [1] "xaxbx" // FastR output: [1] "axxxxxb" assertEval(Ignored.ImplementationError, "{ gsub(pattern = 'Ä*', replacement = 'x', x = 'aÄÄÄÄÄb', perl = TRUE) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java index 4d9589c26e31486799cbcec15d79ccc81d008062..9dbac73a69d7c5abae093953f1b1373f81068ec7 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java @@ -70,9 +70,9 @@ public class TestBuiltin_parse extends TestBase { @Test public void testParseData() { assertEvalFastR("p <- parse(text = 'x = 1', keep.source = TRUE); attr(p, 'srcfile')$parseData", - "structure(c(1L, 1L, 1L, 1L, 1L, 263L, 0L, 0L), text = \"x\", tokens = \"SYMBOL\", class = \"parseData\", .Dim = c(8L, 1L))"); + "structure(c(1L, 3L, 1L, 3L, 1L, 267L, 1L, 5L, 1L, 1L, 1L, 1L, 1L, 263L, 2L, 5L, 1L, 5L, 1L, 5L, 1L, 261L, 3L, 4L, 1L, 5L, 1L, 5L, 0L, 77L, 4L, 5L, 1L, 1L, 1L, 5L, 0L, 77L, 5L, 0L), tokens = c(\"EQ_ASSIGN\", \"SYMBOL\", \"NUM_CONST\", \"expr\", \"expr\"), text = c(\"=\", \"x\", \"1\", \"\", \"\"), class = \"parseData\", .Dim = c(8L, 5L))"); assertEvalFastR("p <- parse(text = 'x = x + 1; rnorm(1, std = z); f2 <- function(a=1) a', keep.source = TRUE); attr(p, 'srcfile')$parseData", - "structure(c(1L, 1L, 1L, 1L, 1L, 263L, 0L, 0L, 1L, 5L, 1L, 5L, 1L, 263L, 1L, 0L, 1L, 12L, 1L, 28L, 1L, 296L, 2L, 0L, 1L, 27L, 1L, 27L, 1L, 263L, 3L, 0L, 1L, 31L, 1L, 32L, 1L, 263L, 4L, 0L, 1L, 51L, 1L, 51L, 1L, 263L, 5L, 0L), text = c(\"x\", \"x\", \"rnorm\", \"z\", \"f2\", \"a\"), tokens = c(\"SYMBOL\", \"SYMBOL\", \"SYMBOL_FUNCTION_CALL\", \"SYMBOL\", \"SYMBOL\", \"SYMBOL\"), class = \"parseData\", .Dim = c(8L, 6L))"); + "structure(c(1L, 3L, 1L, 3L, 1L, 267L, 1L, 8L, 1L, 1L, 1L, 1L, 1L, 263L, 2L, 8L, 1L, 5L, 1L, 5L, 1L, 263L, 3L, 7L, 1L, 7L, 1L, 7L, 1L, 43L, 4L, 7L, 1L, 9L, 1L, 9L, 1L, 261L, 5L, 6L, 1L, 9L, 1L, 9L, 0L, 77L, 6L, 7L, 1L, 5L, 1L, 9L, 0L, 77L, 7L, 8L, 1L, 1L, 1L, 9L, 0L, 77L, 8L, 0L, 1L, 12L, 1L, 16L, 1L, 296L, 9L, 13L, 1L, 18L, 1L, 18L, 1L, 261L, 10L, 11L, 1L, 18L, 1L, 18L, 0L, 77L, 11L, 13L, 1L, 27L, 1L, 27L, 1L, 263L, 12L, 13L, 1L, 12L, 1L, 28L, 0L, 77L, 13L, 0L, 1L, 34L, 1L, 35L, 1L, 266L, 14L, 20L, 1L, 31L, 1L, 32L, 1L, 263L, 15L, 20L, 1L, 48L, 1L, 48L, 1L, 261L, 16L, 17L, 1L, 48L, 1L, 48L, 0L, 77L, 17L, 19L, 1L, 51L, 1L, 51L, 1L, 263L, 18L, 19L, 1L, 37L, 1L, 51L, 1L, 264L, 19L, 20L, 1L, 31L, 1L, 51L, 0L, 77L, 20L, 0L), tokens = c(\"EQ_ASSIGN\", \"SYMBOL\", \"SYMBOL\", \"'+'\", \"NUM_CONST\", \"expr\", \"expr\", \"expr\", \"SYMBOL_FUNCTION_CALL\", \"NUM_CONST\", \"expr\", \"SYMBOL\", \"expr\", \"LEFT_ASSIGN\", \"SYMBOL\", \"NUM_CONST\", \"expr\", \"SYMBOL\", \"FUNCTION\", \"expr\"), text = c(\"=\", \"x\", \"x\", \"+\", \"1\", \"\", \"\", \"\", \"rnorm\", \"1\", \"\", \"z\", \"\", \"<-\", \"f2\", \"1\", \"\", \"a\", \"function\", \"\"), class = \"parseData\", .Dim = c(8L, 20L))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java index ccf9cc0a6af505c946cd22616e20791a9619997e..eb80b28132dd018ce1f2d1248d2db16e95352ccc 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2017, Oracle and/or its affiliates + * Copyright (c) 2013, 2018, Oracle and/or its affiliates * * All rights reserved. */ @@ -66,6 +66,10 @@ public class TestBuiltin_rbind extends TestBase { assertEval("{ rbind(matrix(1:4, nrow=2, dimnames=list(NULL, c('x', 'y'))), c(m=8,n=9)) }"); assertEval("{ rbind(matrix(1:4, nrow=2), z=c(m=8,n=9)) }"); + assertEval("{ rbind(logical(0),matrix(character(0),0,0)) }"); + assertEval("{ rbind(integer(0), NULL, matrix(integer(0),0,1)) }"); + assertEval("{ rbind(integer(0), NULL, matrix(integer(0),1,0)) }"); + assertEval("{ info <- c(\"print\", \"AES\", \"print.AES\") ; ns <- integer(0) ; rbind(info, ns) }"); assertEval("{ x<-list(a=7, b=NULL, c=42); y<-as.data.frame(do.call(rbind,x)); y }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sub.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sub.java index 79ac5f153443783fb40127cbed696bd8c954de66..8832836c9b691b4e131b3428295846c9e52b8c71 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sub.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sub.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2017, Oracle and/or its affiliates + * Copyright (c) 2013, 2018, Oracle and/or its affiliates * * All rights reserved. */ @@ -150,6 +150,8 @@ public class TestBuiltin_sub extends TestBase { assertEval("{ .Internal(sub(\"7\", character(), \"7\", F, F, F, F)) }"); assertEval("{ .Internal(sub(\"7\", \"42\", 7, F, F, F, F)) }"); + assertEval("{ sub('~', '\\\\\\\\X', '~') }"); + assertEval("{ sub('\\\\s*$', '', 'Ä', perl=TRUE) }"); assertEval("{ sub(pattern = 'a*', replacement = 'x', x = 'ÄaÄ', perl = TRUE) }");