From 8490a119f7a504c85597ce1b33021b004bc5ba06 Mon Sep 17 00:00:00 2001 From: Adam Welc <adam.welc@oracle.com> Date: Fri, 7 Nov 2014 14:54:00 +0100 Subject: [PATCH] Further enhancements to factor and data frame support. Fixed an argument matching bug. --- .../com/oracle/truffle/r/engine/REngine.java | 1 - .../r/nodes/builtin/base/AsCharacter.java | 7 +- .../truffle/r/nodes/builtin/base/Dim.java | 18 +++-- .../r/nodes/builtin/base/DimNames.java | 10 +-- .../nodes/builtin/base/ForeignFunctions.java | 17 +--- .../r/nodes/builtin/base/TypeConvert.java | 4 +- .../access/array/read/AccessArrayNode.java | 9 +++ .../access/array/write/CoerceVector.java | 35 +++++---- .../array/write/UpdateArrayHelperNode.java | 34 +++++++- .../r/nodes/function/ArgumentMatcher.java | 8 +- .../truffle/r/runtime/data/RDataFrame.java | 5 ++ .../truffle/r/runtime/data/RExpression.java | 4 + .../truffle/r/runtime/data/RFactor.java | 5 ++ .../truffle/r/runtime/data/RLanguage.java | 5 ++ .../truffle/r/runtime/data/RPairList.java | 4 + .../truffle/r/runtime/data/RVector.java | 6 +- .../data/model/RAbstractContainer.java | 2 + .../truffle/r/test/ExpectedTestOutput.test | 78 +++++++++++++++++++ .../oracle/truffle/r/test/all/AllTests.java | 55 +++++++++++++ .../r/test/simple/TestSimpleBuiltins.java | 7 ++ .../r/test/simple/TestSimpleDataFrames.java | 8 ++ .../r/test/simple/TestSimpleFunctions.java | 4 + 22 files changed, 269 insertions(+), 57 deletions(-) diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java index fe2eb079f4..ec84baa9ed 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java @@ -282,7 +282,6 @@ public final class REngine implements RContext.Engine { ConsoleHandler ch = singleton.context.getConsoleHandler(); ch.println("Unsupported specialization in node " + use.getNode().getClass().getSimpleName() + " - supplied values: " + Arrays.asList(use.getSuppliedValues()).stream().map(v -> v.getClass().getSimpleName()).collect(Collectors.toList())); - use.printStackTrace(); return null; } catch (RecognitionException | RuntimeException e) { singleton.context.getConsoleHandler().println("Exception while parsing: " + e); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java index 72f437bf2d..aeb370ad79 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java @@ -161,7 +161,12 @@ public abstract class AsCharacter extends RBuiltinNode { return RDataFactory.createStringVector(data, RDataFactory.INCOMPLETE_VECTOR); } else { for (int i = 0; i < data.length; i++) { - data[i] = vec.getDataAt(value.getVector().getDataAt(i) - 1); + int val = value.getVector().getDataAt(i); + if (RRuntime.isNA(val)) { + data[i] = RRuntime.NA_HEADER; + } else { + data[i] = vec.getDataAt(val - 1); + } } return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java index 64fe80b7d8..b3da390c39 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java @@ -73,16 +73,16 @@ public abstract class Dim extends RBuiltinNode { return RNull.instance; } - @Specialization(guards = "!hasDimensions") - protected RNull dim(RAbstractVector vector) { + @Specialization(guards = {"!hasDimensions", "!isDataFrame"}) + protected RNull dim(RAbstractContainer container) { controlVisibility(); return RNull.instance; } - @Specialization(guards = "hasDimensions") - protected RIntVector dimWithDimensions(RAbstractVector vector) { + @Specialization(guards = {"hasDimensions", "!isDataFrame"}) + protected RIntVector dimWithDimensions(RAbstractContainer container) { controlVisibility(); - return RDataFactory.createIntVector(vector.getDimensions(), RDataFactory.COMPLETE_VECTOR); + return RDataFactory.createIntVector(container.getDimensions(), RDataFactory.COMPLETE_VECTOR); } @Specialization @@ -91,8 +91,12 @@ public abstract class Dim extends RBuiltinNode { return RDataFactory.createIntVector(new int[]{dataFrameRowNames(frame, dataFrame), dataFrame.getLength()}, RDataFactory.COMPLETE_VECTOR); } - public static boolean hasDimensions(RAbstractVector vector) { - return vector.hasDimensions(); + public static boolean isDataFrame(RAbstractContainer container) { + return container.getElementClass() == RDataFrame.class; + } + + public static boolean hasDimensions(RAbstractContainer container) { + return container.hasDimensions(); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java index 49fa4b5ef0..e1edbd2628 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java @@ -40,19 +40,19 @@ public abstract class DimNames extends RBuiltinNode { } @Specialization(guards = "!isNull") - protected RList getDimNames(RAbstractVector vector) { + protected RList getDimNames(RAbstractContainer container) { controlVisibility(); - return vector.getDimNames(); + return container.getDimNames(); } @Specialization(guards = "isNull") - protected RNull getDimNamesNull(@SuppressWarnings("unused") RAbstractVector vector) { + protected RNull getDimNamesNull(@SuppressWarnings("unused") RAbstractContainer vector) { controlVisibility(); return RNull.instance; } - protected boolean isNull(RAbstractVector vector) { - return vector.getDimNames() == null; + protected boolean isNull(RAbstractContainer container) { + return container.getDimNames() == null; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForeignFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForeignFunctions.java index 41bb9c8ada..27659bc2c4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForeignFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForeignFunctions.java @@ -579,10 +579,9 @@ public class ForeignFunctions { // Transcribed from GnuR, library/utils/src/io.c @TruffleBoundary @Specialization(guards = "isWriteTable") - protected Object doWriteTable(VirtualFrame frame, RList f, RArgsValuesAndNames args) { + protected Object doWriteTable(VirtualFrame frame, @SuppressWarnings("unused") RList f, RArgsValuesAndNames args) { controlVisibility(); Object[] argValues = args.getValues(); - Object x = argValues[0]; Object con = argValues[1]; if (!(con instanceof RConnection)) { throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, "'file' is not a connection"); @@ -599,9 +598,6 @@ public class ForeignFunctions { Object quoteArg = argValues[9]; byte qmethod = castLogical(frame, argValues[10]); - String sep; - String eol; - String na; String dec; if (nr == RRuntime.INT_NA) { @@ -613,13 +609,13 @@ public class ForeignFunctions { if (!(rnamesArg instanceof RNull) && isString(rnamesArg) == null) { invalidArgument("rnames"); } - if ((sep = isString(sepArg)) == null) { + if (isString(sepArg) == null) { invalidArgument("sep"); } - if ((eol = isString(eolArg)) == null) { + if (isString(eolArg) == null) { invalidArgument("eol"); } - if ((na = isString(naArg)) == null) { + if (isString(naArg) == null) { invalidArgument("na"); } if ((dec = isString(decArg)) == null) { @@ -631,15 +627,10 @@ public class ForeignFunctions { if (dec.length() != 1) { throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, "'dec' must be a single character"); } - char cdec = dec.charAt(0); boolean[] quoteCol = new boolean[nc]; - boolean quoteRn = false; RIntVector quote = (RIntVector) quoteArg; for (int i = 0; i < quote.getLength(); i++) { int qi = quote.getDataAt(i); - if (qi == 0) { - quoteRn = true; - } if (qi > 0) { quoteCol[qi - 1] = true; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TypeConvert.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TypeConvert.java index 03ef8a58d2..0c2b3c7a78 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TypeConvert.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TypeConvert.java @@ -163,8 +163,8 @@ public abstract class TypeConvert extends RBuiltinNode { } } RIntVector res = RDataFactory.createIntVector(data, complete); - res.setAttr("levels", RDataFactory.createStringVector(levelsArray, RDataFactory.COMPLETE_VECTOR)); - res.setAttr("class", RDataFactory.createStringVector("factor")); + res.setLevels(RDataFactory.createStringVector(levelsArray, RDataFactory.COMPLETE_VECTOR)); + RVector.setClassAttr(res, RDataFactory.createStringVector("factor"), null, null); return RDataFactory.createFactor(res); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/AccessArrayNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/AccessArrayNode.java index e853324fdf..16c744e70c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/AccessArrayNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/AccessArrayNode.java @@ -184,6 +184,15 @@ public abstract class AccessArrayNode extends RNode { return RDataFactory.createStringVector(namesData, namesNACheck.neverSeenNA()); } + // TODO: ultimately factor accesses should be turned into generic function + @Specialization + protected Object accessFactor(VirtualFrame frame, RFactor factor, int recLevel, Object position, RAbstractLogicalVector dropDim) { + RIntVector res = (RIntVector) castVector(frame, accessRecursive(frame, factor.getVector(), position, recLevel, dropDim)); + res.setLevels(factor.getVector().getAttr(RRuntime.LEVELS_ATTR_KEY)); + RVector.setClassAttr(res, RDataFactory.createStringVector("factor"), null, null); + return RDataFactory.createFactor(res); + } + @SuppressWarnings("unused") @Specialization(guards = {"inRecursion", "isFirstPositionPositive"}) protected RNull accessNullInRecursionPosPositive(RNull vector, int recLevel, RAbstractIntVector positions, RAbstractLogicalVector dropDim) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/CoerceVector.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/CoerceVector.java index eec8bfc66d..d6d5c8f5ea 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/CoerceVector.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/CoerceVector.java @@ -129,8 +129,8 @@ public abstract class CoerceVector extends RNode { throw RError.error(getEncapsulatingSourceSection(), RError.Message.SUBASSIGN_TYPE_FIX, "integer", "raw"); } - @Specialization - protected RList coerce(VirtualFrame frame, RAbstractIntVector value, RList vector, Object operand) { + @Specialization(guards = "isVectorListOrDataFrame") + protected RAbstractContainer coerce(VirtualFrame frame, RAbstractIntVector value, RAbstractContainer vector, Object operand) { return vector; } @@ -167,7 +167,7 @@ public abstract class CoerceVector extends RNode { } @Specialization - protected RList coerce(VirtualFrame frame, RAbstractDoubleVector value, RList vector, Object operand) { + protected RAbstractContainer coerce(VirtualFrame frame, RAbstractDoubleVector value, RAbstractContainer vector, Object operand) { return vector; } @@ -203,8 +203,8 @@ public abstract class CoerceVector extends RNode { throw RError.error(getEncapsulatingSourceSection(), RError.Message.SUBASSIGN_TYPE_FIX, "logical", "raw"); } - @Specialization - protected RList coerce(VirtualFrame frame, RAbstractLogicalVector value, RList vector, Object operand) { + @Specialization(guards = "isVectorListOrDataFrame") + protected RAbstractContainer coerce(VirtualFrame frame, RAbstractLogicalVector value, RAbstractContainer vector, Object operand) { return vector; } @@ -240,8 +240,8 @@ public abstract class CoerceVector extends RNode { throw RError.error(getEncapsulatingSourceSection(), RError.Message.SUBASSIGN_TYPE_FIX, "character", "raw"); } - @Specialization - protected RList coerce(VirtualFrame frame, RAbstractStringVector value, RList vector, Object operand) { + @Specialization(guards = "isVectorListOrDataFrame") + protected RAbstractContainer coerce(VirtualFrame frame, RAbstractStringVector value, RAbstractContainer vector, Object operand) { return vector; } @@ -277,8 +277,8 @@ public abstract class CoerceVector extends RNode { throw RError.error(getEncapsulatingSourceSection(), RError.Message.SUBASSIGN_TYPE_FIX, "complex", "raw"); } - @Specialization - protected RList coerce(VirtualFrame frame, RAbstractComplexVector value, RList vector, Object operand) { + @Specialization(guards = "isVectorListOrDataFrame") + protected RAbstractContainer coerce(VirtualFrame frame, RAbstractComplexVector value, RAbstractContainer vector, Object operand) { return vector; } @@ -294,15 +294,15 @@ public abstract class CoerceVector extends RNode { throw RError.error(getEncapsulatingSourceSection(), RError.Message.SUBASSIGN_TYPE_FIX, "raw", RRuntime.classToString(vector.getElementClass(), false)); } - @Specialization - protected RList coerce(VirtualFrame frame, RAbstractRawVector value, RList vector, Object operand) { + @Specialization(guards = "isVectorListOrDataFrame") + protected RAbstractContainer coerce(VirtualFrame frame, RAbstractRawVector value, RAbstractContainer vector, Object operand) { return vector; } // list vector value - @Specialization - protected RList coerce(VirtualFrame frame, RList value, RList vector, Object operand) { + @Specialization(guards = "isVectorListOrDataFrame") + protected RAbstractContainer coerce(VirtualFrame frame, RList value, RAbstractContainer vector, Object operand) { return vector; } @@ -314,21 +314,21 @@ public abstract class CoerceVector extends RNode { // data frame value @Specialization - protected RList coerce(VirtualFrame frame, RDataFrame value, RAbstractVector vector, Object operand) { + protected RList coerce(VirtualFrame frame, RDataFrame value, RAbstractContainer vector, Object operand) { return (RList) castList(frame, vector); } // factor value @Specialization - protected Object coerce(VirtualFrame frame, RFactor value, RAbstractVector vector, Object operand) { + protected Object coerce(VirtualFrame frame, RFactor value, RAbstractContainer vector, Object operand) { return coerceRecursive(frame, value.getVector(), vector, operand); } // function vector value @Specialization - protected RFunction coerce(RFunction value, RAbstractVector vector, Object operand) { + protected RFunction coerce(RFunction value, RAbstractContainer vector, Object operand) { throw RError.error(getEncapsulatingSourceSection(), RError.Message.SUBASSIGN_TYPE_FIX, "closure", RRuntime.classToString(vector.getElementClass(), false)); } @@ -358,4 +358,7 @@ public abstract class CoerceVector extends RNode { return vector.getElementClass() == Object.class; } + protected boolean isVectorListOrDataFrame(RAbstractContainer value, RAbstractContainer vector) { + return vector.getElementClass() == Object.class || vector.getElementClass() == RDataFrame.class; + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/UpdateArrayHelperNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/UpdateArrayHelperNode.java index 6a1cfd0c93..1b3c4aeb31 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/UpdateArrayHelperNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/UpdateArrayHelperNode.java @@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.access.array.write; import java.util.*; import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.source.*; @@ -58,6 +59,8 @@ public abstract class UpdateArrayHelperNode extends RNode { protected abstract Object executeUpdate(VirtualFrame frame, Object v, Object value, int recLevel, Object positions, Object vector); + @CompilationFinal private boolean recursiveIsSubset; + @Child private UpdateArrayHelperNode updateRecursive; @Child private CastComplexNode castComplex; @Child private CastDoubleNode castDouble; @@ -84,18 +87,30 @@ public abstract class UpdateArrayHelperNode extends RNode { public UpdateArrayHelperNode(boolean isSubset) { this.isSubset = isSubset; + this.recursiveIsSubset = isSubset; } public UpdateArrayHelperNode(UpdateArrayHelperNode other) { this.isSubset = other.isSubset; + this.recursiveIsSubset = other.recursiveIsSubset; } - private Object updateRecursive(VirtualFrame frame, Object v, Object value, Object vector, Object operand, int recLevel) { - if (updateRecursive == null) { + private Object updateRecursive(VirtualFrame frame, Object v, Object value, Object vector, Object operand, int recLevel, boolean forDataFrame) { + // for data frames, recursive update is the same as for lists but as if the [[]] operator + // was used + if (updateRecursive == null || (forDataFrame && isSubset) || (!forDataFrame && isSubset != recursiveIsSubset)) { CompilerDirectives.transferToInterpreterAndInvalidate(); - updateRecursive = insert(UpdateArrayHelperNodeFactory.create(this.isSubset, null, null, null, null, null)); + boolean newIsSubset = this.isSubset; + if (forDataFrame && isSubset) { + newIsSubset = false; + } + updateRecursive = insert(UpdateArrayHelperNodeFactory.create(newIsSubset, null, null, null, null, null)); } - return executeUpdate(frame, v, value, recLevel, operand, vector); + return updateRecursive.executeUpdate(frame, v, value, recLevel, operand, vector); + } + + private Object updateRecursive(VirtualFrame frame, Object v, Object value, Object vector, Object operand, int recLevel) { + return updateRecursive(frame, v, value, vector, operand, recLevel, false); } private Object castComplex(VirtualFrame frame, Object operand) { @@ -177,6 +192,17 @@ public abstract class UpdateArrayHelperNode extends RNode { return CastToContainerNodeFactory.create(child, false, false, false, true); } + @Specialization + protected Object update(VirtualFrame frame, Object v, Object value, int recLevel, Object positions, RDataFrame vector) { + RVector inner = vector.getVector(); + RVector res = (RVector) updateRecursive(frame, v, value, inner, positions, recLevel, true); + if (res != inner) { + return RDataFactory.createDataFrame(res); + } else { + return vector; + } + } + @Specialization protected Object update(VirtualFrame frame, Object v, RFactor value, int recLevel, Object positions, Object vector) { return updateRecursive(frame, v, value.getVector(), vector, positions, recLevel); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java index 85da4d6557..4bb6e4b09d 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java @@ -309,7 +309,7 @@ public class ArgumentMatcher { } // Search for argument name inside formal arguments - int fi = findParameterPosition(formalNames, suppliedNames[si], matchedFormalArgs, si, hasVarArgs, suppliedArgs[si], callSrc, argsSrc); + int fi = findParameterPosition(formalNames, suppliedNames[si], matchedFormalArgs, si, hasVarArgs, suppliedArgs[si], callSrc, argsSrc, varArgIndex); if (fi >= 0) { resultArgs[fi] = suppliedArgs[si]; matchedSuppliedArgs.set(si); @@ -497,12 +497,13 @@ public class ArgumentMatcher { * @param debugArgNode * @param callSrc * @param argsSrc + * @param varArgIndex * * @return The position of the given suppliedName inside the formalNames. Throws errors if the * argument has been matched before */ private static <T> int findParameterPosition(String[] formalNames, String suppliedName, BitSet matchedSuppliedArgs, int suppliedIndex, boolean hasVarArgs, T debugArgNode, SourceSection callSrc, - SourceSection argsSrc) { + SourceSection argsSrc, int varArgIndex) { int found = -1; for (int i = 0; i < formalNames.length; i++) { if (formalNames[i] == null) { @@ -518,7 +519,8 @@ public class ArgumentMatcher { } matchedSuppliedArgs.set(found); break; - } else if (!suppliedName.isEmpty() && formalName.startsWith(suppliedName)) { + } else if (!suppliedName.isEmpty() && formalName.startsWith(suppliedName) && ((varArgIndex != FormalArguments.NO_VARARG && i < varArgIndex) || varArgIndex == FormalArguments.NO_VARARG)) { + // partial-match only if the formal argument is positioned before ... if (found >= 0) { throw RError.error(argsSrc, RError.Message.ARGUMENT_MATCHES_MULTIPLE, 1 + suppliedIndex); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFrame.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFrame.java index d008396f97..3937de107a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFrame.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFrame.java @@ -71,6 +71,11 @@ public final class RDataFrame implements RShareable, RAbstractContainer { return vector.getAttributes(); } + @Override + public boolean hasDimensions() { + return vector.hasDimensions(); + } + @Override public int[] getDimensions() { return vector.getDimensions(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java index c4ee0a45e9..0d3e587552 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java @@ -52,6 +52,10 @@ public class RExpression implements RShareable, RAbstractContainer { return data.getLength(); } + public boolean hasDimensions() { + return data.hasDimensions(); + } + public int[] getDimensions() { return data.getDimensions(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java index f58a701846..2d4d8aa74e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java @@ -71,6 +71,11 @@ public final class RFactor implements RShareable, RAbstractContainer { return vector.getAttributes(); } + @Override + public boolean hasDimensions() { + return vector.hasDimensions(); + } + @Override public int[] getDimensions() { return vector.getDimensions(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java index b664d05590..6bf246f615 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java @@ -72,6 +72,11 @@ public class RLanguage extends RLanguageRep implements RAbstractContainer, RAttr return length; } + public boolean hasDimensions() { + // TODO + return false; + } + public int[] getDimensions() { // TODO return null; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java index 6e5ac36178..add5a33aaf 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java @@ -123,6 +123,10 @@ public class RPairList implements RAttributable, RAbstractContainer { return result; } + public boolean hasDimensions() { + return true; + } + public int[] getDimensions() { return new int[]{1}; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java index f4a3e81da5..3db2391caf 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java @@ -369,11 +369,7 @@ public abstract class RVector extends RBounded implements RShareable, RAbstractV } public final int[] getDimensions() { - if (hasDimensions()) { - return dimensions; - } else { - return null; - } + return dimensions; } public final void setDimensions(int[] newDimensions) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java index 73dfc6e291..8c30453933 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java @@ -28,6 +28,8 @@ public interface RAbstractContainer extends RAttributable, RClassHierarchy { int getLength(); + boolean hasDimensions(); + int[] getDimensions(); Class<?> getElementClass(); 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 399d70f1cf..605937e8f3 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 @@ -8357,6 +8357,36 @@ In Ops.factor(x, "a") : > not meaningful for factors Warning message: In Ops.factor(x, c("a", "b")) : > not meaningful for factors +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-factor(c("a", "b", "a")); x[1] } +[1] a +Levels: a b + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-factor(c("a", "b", "a")); x[2] } +[1] b +Levels: a b + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-factor(c("a", "b", "a")); x[[1]] } +[1] a +Levels: a b + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-factor(c("a", "b", "a")); x[[2]] } +[1] b +Levels: a b + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-factor(c("a", "b", "a")); x[c(1,2)] } +[1] a b +Levels: a b + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-factor(c("a", "b", "a")); x[c(1,2,3,4)] } +[1] a b a <NA> +Levels: a b + ##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor #{ x<-factor(c("a", "b", "a", "c")); x == c("a", "b") } [1] TRUE TRUE TRUE FALSE @@ -16240,6 +16270,20 @@ $x [1] FALSE TRUE TRUE +##com.oracle.truffle.r.test.simple.TestSimpleDataFrames.testMisc +#{ n = c(2, 3, 5); s = c("aa", "bb", "cc"); df = data.frame(n, s); df[[1]] <- c(22,33,55); df } + n s +1 22 aa +2 33 bb +3 55 cc + +##com.oracle.truffle.r.test.simple.TestSimpleDataFrames.testPrint +#{ n = c(2, 3, 5); s = c(TRUE, FALSE, TRUE); df = data.frame(n, s); df } + n s +1 2 TRUE +2 3 FALSE +3 5 TRUE + ##com.oracle.truffle.r.test.simple.TestSimpleDataFrames.testPrint #{ x<-c(1,2); class(x)<-"data.frame"; row.names(x)<-integer(); x } NULL @@ -16257,6 +16301,13 @@ NULL 1 7 2 42 +##com.oracle.truffle.r.test.simple.TestSimpleDataFrames.testPrint +#{ x<-data.frame(n=c("2", "3", "5"), s=c("TRUE", "FALSE", "TRUE"), check.names=FALSE, row.names=c("1", "2", "3")); x } + n s +1 2 TRUE +2 3 FALSE +3 5 TRUE + ##com.oracle.truffle.r.test.simple.TestSimpleDataFrames.testPrint #{ x<-integer(); class(x)<-"data.frame"; x } data frame with 0 columns and 0 rows @@ -16954,6 +17005,33 @@ Error in f(h = 1) : argument 1 matches multiple formal arguments #{ f <- function(hello, hi) { hello + hi } ; f(hello = 1, bye = 3) } Error in f(hello = 1, bye = 3) : unused argument (bye = 3) +##com.oracle.truffle.r.test.simple.TestSimpleFunctions.testMatching +#{ f<-function(..., val=1) { c(list(...), val) }; f(v=7, 2) } +$v +[1] 7 + +[[2]] +[1] 2 + +[[3]] +[1] 1 + + +##com.oracle.truffle.r.test.simple.TestSimpleFunctions.testMatching +#{ f<-function(er=1, ..., val=1) { c(list(...), val, er) }; f(v=7, 2, e=8) } +$v +[1] 7 + +[[2]] +[1] 2 + +[[3]] +[1] 1 + +[[4]] +[1] 8 + + ##com.oracle.truffle.r.test.simple.TestSimpleFunctions.testMatching #{ x<-function(foo,bar){foo*bar} ; x(f=10,2) } [1] 20 diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java index 62fa512c88..7bd93077b9 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java @@ -8123,6 +8123,36 @@ public class AllTests extends TestBase { assertEval("{ x<-factor(c(\"a\", \"b\", \"a\", \"c\")); x == c(\"a\", \"b\") }"); } + @Test + public void TestSimpleBuiltins_testFactor_ef37cc56e92b1c4a3742f47b97df2525() { + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); x[1] }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_e1467f269d5a2fed20d121b42b6669e7() { + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); x[[1]] }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_49d94f4cc6d874fdd626f78a760dd79e() { + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); x[2] }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_b1b8488bfeafbcf09b786073c66c0a31() { + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); x[[2]] }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_9c518bdf01e419e3635b3da6dd82b34a() { + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); x[c(1,2)] }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_1d1ee9908bd60f3714927a245349a33e() { + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); x[c(1,2,3,4)] }"); + } + @Test public void TestSimpleBuiltins_testFactor_2ef7de52def309425a9b70965111f004() { assertEvalError("{ x<-c(1,2,3); class(x)<-\"factor\"; x }"); @@ -17058,6 +17088,11 @@ public class AllTests extends TestBase { assertEval("{ x <- c(1, 2, 3); xa <- as.data.frame(x); lapply(xa, function(x) x > 1) }"); } + @Test + public void TestSimpleDataFrames_testMisc_19e026dd42148710ae11cdde5dc3b73e() { + assertEval("{ n = c(2, 3, 5); s = c(\"aa\", \"bb\", \"cc\"); df = data.frame(n, s); df[[1]] <- c(22,33,55); df }"); + } + @Test public void TestSimpleDataFrames_testPrint_da9c92f6582f469a3303b14bf936c77e() { assertEval("{x<-c(1,2); class(x)<-\"data.frame\"; x}"); @@ -17083,6 +17118,16 @@ public class AllTests extends TestBase { assertEval("{ x<-c(7,42); y<-data.frame(x); y }"); } + @Test + public void TestSimpleDataFrames_testPrint_674621fc7276825fddf39eadfa8b8e45() { + assertEval("{ n = c(2, 3, 5); s = c(TRUE, FALSE, TRUE); df = data.frame(n, s); df }"); + } + + @Test + public void TestSimpleDataFrames_testPrint_a7771c300d3a272d55b6385a70e8b9b5() { + assertEval("{ x<-data.frame(n=c(\"2\", \"3\", \"5\"), s=c(\"TRUE\", \"FALSE\", \"TRUE\"), check.names=FALSE, row.names=c(\"1\", \"2\", \"3\")); x }"); + } + @Test public void TestSimpleDataFrames_testRowNames_a3af62479ea621f4e185c40355da07ce() { assertEval("{ x<-c(1,2); row.names(x)<-NULL; attributes(x) }"); @@ -17953,6 +17998,16 @@ public class AllTests extends TestBase { assertEval("{ x<-function(foo,bar){foo*bar} ; x(fo=10, bar=2) }"); } + @Test + public void TestSimpleFunctions_testMatching_3044cf7c3e46ee0ed1d82185d7fa28f8() { + assertEval("{ f<-function(..., val=1) { c(list(...), val) }; f(v=7, 2) }"); + } + + @Test + public void TestSimpleFunctions_testMatching_a44e5e17d1cee7de52a7be40ceccc694() { + assertEval("{ f<-function(er=1, ..., val=1) { c(list(...), val, er) }; f(v=7, 2, e=8) }"); + } + @Test public void TestSimpleFunctions_testMatching_7c113e0683905a2c65072aebc1cf14dc() { assertEvalError("{ f <- function(hello, hi) { hello + hi } ; f(h = 1) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java index 90888984d5..d66c062c8b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java @@ -3910,6 +3910,13 @@ public class TestSimpleBuiltins extends TestBase { assertEvalWarning("{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-list(1); y[1]<-x; y }"); assertEvalWarning("{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-c(1); y[1]<-x; y }"); + + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); x[1] }"); + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); x[[1]] }"); + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); x[2] }"); + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); x[[2]] }"); + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); x[c(1,2)] }"); + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); x[c(1,2,3,4)] }"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleDataFrames.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleDataFrames.java index 2ec6c750ba..8a9644e161 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleDataFrames.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleDataFrames.java @@ -122,6 +122,8 @@ public class TestSimpleDataFrames extends TestBase { assertEval("{ x<-c(1,2); y<-data.frame(x); y }"); assertEval("{ x<-c(7,42); y<-data.frame(x); y }"); + assertEval("{ n = c(2, 3, 5); s = c(TRUE, FALSE, TRUE); df = data.frame(n, s); df }"); + assertEval("{ x<-data.frame(n=c(\"2\", \"3\", \"5\"), s=c(\"TRUE\", \"FALSE\", \"TRUE\"), check.names=FALSE, row.names=c(\"1\", \"2\", \"3\")); x }"); } @Test @@ -135,4 +137,10 @@ public class TestSimpleDataFrames extends TestBase { public void testLapply() { assertEval("{ x <- c(1, 2, 3); xa <- as.data.frame(x); lapply(xa, function(x) x > 1) }"); } + + @Test + public void testMisc() { + assertEval("{ n = c(2, 3, 5); s = c(\"aa\", \"bb\", \"cc\"); df = data.frame(n, s); df[[1]] <- c(22,33,55); df }"); + } + } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleFunctions.java index b054e01227..67de58daf9 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleFunctions.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleFunctions.java @@ -168,6 +168,10 @@ public class TestSimpleFunctions extends TestBase { assertEvalError("{ f <- function(hello, hi) { hello + hi } ; f(h = 1) }"); assertEvalError("{ f <- function(hello, hi) { hello + hi } ; f(hello = 1, bye = 3) }"); assertEvalError("{ f <- function(a) { a } ; f(1,2) }"); + + // with ... partial-match only if formal parameter are before ... + assertEval("{ f<-function(..., val=1) { c(list(...), val) }; f(v=7, 2) }"); + assertEval("{ f<-function(er=1, ..., val=1) { c(list(...), val, er) }; f(v=7, 2, e=8) }"); } @Test -- GitLab