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 fe2eb079f49965a9bee08d91dbbc37b11f1d4a35..ec84baa9ed60d1161117164700bfa7e8d2c38e46 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/AnyDuplicated.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyDuplicated.java index 6a090aa20916500a2b7eef0d6a7fd80b3bc9259b..9f26ab728d2741459b29f24c1ae7882c02632193 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyDuplicated.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyDuplicated.java @@ -69,24 +69,24 @@ public abstract class AnyDuplicated extends RBuiltinNode { } @Specialization(guards = {"!empty"}) - protected int anyDuplicatedFromStart(VirtualFrame frame, RAbstractVector x, RAbstractVector incomparables, byte fromLast) { + protected int anyDuplicatedFromStart(VirtualFrame frame, RAbstractContainer x, RAbstractContainer incomparables, byte fromLast) { initChildren(); RType xType = typeof.execute(frame, x); if (fromLastProfile.profile(fromLast == RRuntime.LOGICAL_TRUE)) { - return getIndexFromLast(x, (RAbstractVector) (castTypeNode.execute(frame, incomparables, xType))); + return getIndexFromLast(x, (RAbstractContainer) (castTypeNode.execute(frame, incomparables, xType))); } else { - return getIndexFromStart(x, (RAbstractVector) (castTypeNode.execute(frame, incomparables, xType))); + return getIndexFromStart(x, (RAbstractContainer) (castTypeNode.execute(frame, incomparables, xType))); } } @SuppressWarnings("unused") @Specialization(guards = "empty") - protected int anyDuplicatedEmpty(RAbstractVector x, RAbstractVector incomparables, byte fromLast) { + protected int anyDuplicatedEmpty(RAbstractContainer x, RAbstractContainer incomparables, byte fromLast) { return 0; } @TruffleBoundary - private static int getIndexFromStart(RAbstractVector x, RAbstractVector incomparables) { + private static int getIndexFromStart(RAbstractContainer x, RAbstractContainer incomparables) { HashSet<Object> incompContents = new HashSet<>(); HashSet<Object> vectorContents = new HashSet<>(); for (int i = 0; i < incomparables.getLength(); i++) { @@ -106,7 +106,7 @@ public abstract class AnyDuplicated extends RBuiltinNode { } @TruffleBoundary - private static int getIndexFromStart(RAbstractVector x) { + private static int getIndexFromStart(RAbstractContainer x) { HashSet<Object> vectorContents = new HashSet<>(); vectorContents.add(x.getDataAtAsObject(0)); for (int i = 1; i < x.getLength(); i++) { @@ -120,7 +120,7 @@ public abstract class AnyDuplicated extends RBuiltinNode { } @TruffleBoundary - public static int getIndexFromLast(RAbstractVector x, RAbstractVector incomparables) { + public static int getIndexFromLast(RAbstractContainer x, RAbstractContainer incomparables) { HashSet<Object> incompContents = new HashSet<>(); HashSet<Object> vectorContents = new HashSet<>(); for (int i = 0; i < incomparables.getLength(); i++) { @@ -140,7 +140,7 @@ public abstract class AnyDuplicated extends RBuiltinNode { } @TruffleBoundary - private static int getIndexFromLast(RAbstractVector x) { + private static int getIndexFromLast(RAbstractContainer x) { HashSet<Object> vectorContents = new HashSet<>(); vectorContents.add(x.getDataAtAsObject(x.getLength() - 1)); for (int i = x.getLength() - 2; i >= 0; i--) { @@ -154,11 +154,11 @@ public abstract class AnyDuplicated extends RBuiltinNode { } @SuppressWarnings("unused") - protected boolean isIncomparable(RAbstractVector x, byte incomparables, byte fromLast) { + protected boolean isIncomparable(RAbstractContainer x, byte incomparables, byte fromLast) { return incomparables == RRuntime.LOGICAL_TRUE; } - protected boolean empty(RAbstractVector x) { + protected boolean empty(RAbstractContainer x) { return x.getLength() == 0; } 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 72f437bf2d5276c9b0301e3ef1223cd9c2ac170f..aeb370ad79feb51187e6a06efdeb31e75b1997b8 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/AsDouble.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java index 096951c0d0e09ca6ebd44d29da4065f9be98b8c8..d60ee330421bcaa84241df1241b4919948070434 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java @@ -137,4 +137,10 @@ public abstract class AsDouble extends RBuiltinNode { controlVisibility(); return castDoubleVector(frame, vector); } + + @Specialization + protected RDoubleVector asDouble(VirtualFrame frame, RFactor vector) { + return asDouble(frame, vector.getVector()); + } + } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java index ff874767f293d04fa9151e12ff93417bd7039150..547ba5daa653a3603df949dab407907cc2343015 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java @@ -133,8 +133,7 @@ public abstract class AsInteger extends RBuiltinNode { @Specialization protected RIntVector asInteger(RFactor factor) { - controlVisibility(); - return factor.getVector(); + return asInteger(factor.getVector()); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java index 2a18bb988bb34c4d0a1dba2b21dcb9ea6b3ba7fc..b50cb5243b83a66f7baa7e48188d76b3fec04310 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java @@ -101,8 +101,8 @@ public abstract class AsLogical extends RBuiltinNode { } @Specialization - protected RLogicalVector asLogical(VirtualFrame frame, RAbstractVector vector) { + protected RLogicalVector asLogical(VirtualFrame frame, RAbstractContainer container) { controlVisibility(); - return castLogicalVector(frame, vector); + return castLogicalVector(frame, container); } } 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 8d22b579121f52be4927c7d92137a1c215b342b5..de7553e14890f9674cfdf7752798dc06741e9fd6 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 @@ -168,6 +168,12 @@ public abstract class ConnectionFunctions { return theConnection.getInputStream(); } + @Override + public OutputStream getOutputStream() throws IOException { + checkOpen(); + return theConnection.getOutputStream(); + } + @Override public void writeLines(RAbstractStringVector lines, String sep) throws IOException { checkOpen(); @@ -233,6 +239,10 @@ public abstract class ConnectionFunctions { // nothing to do } + @Override + public OutputStream getOutputStream() { + throw RInternalError.shouldNotReachHere(); + } } private abstract static class DelegateWriteRConnection extends DelegateRConnection { @@ -245,6 +255,11 @@ public abstract class ConnectionFunctions { throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message); } + @Override + public InputStream getInputStream() { + throw RInternalError.shouldNotReachHere(); + } + } /** @@ -285,6 +300,11 @@ public abstract class ConnectionFunctions { throw RInternalError.shouldNotReachHere(); } + @Override + public OutputStream getOutputStream() { + throw RInternalError.shouldNotReachHere(); + } + @Override public void close() throws IOException { throw RInternalError.shouldNotReachHere(); @@ -400,8 +420,8 @@ public abstract class ConnectionFunctions { } @Override - public InputStream getInputStream() throws IOException { - throw RInternalError.shouldNotReachHere(); + public OutputStream getOutputStream() throws IOException { + return outputStream; } @Override 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 64fe80b7d89ee025dbd2e0d933a8db63ee57701e..b3da390c39b65835322cee41edf31a25468ecb7f 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 49fa4b5ef08f8a5570eb2e54d7f26bc913edb23c..e1edbd2628f6c5776f3a6da68b68ff07ed8dc45c 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/DynLoadFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java index a881407971880e04ca684dc1a66dd08129e1c4d9..ebf063b71dffefaff13aaf04a55a5eed6eb5f286 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java @@ -100,14 +100,14 @@ public class DynLoadFunctions { data[i] = dllInfo; } RList result = RDataFactory.createList(data, RDataFactory.createStringVector(names, RDataFactory.COMPLETE_VECTOR)); - RVector.setClassAttr(result, RDataFactory.createStringVectorFromScalar(DLLINFOLIST_CLASS), null, null); + RVector.setVectorClassAttr(result, RDataFactory.createStringVectorFromScalar(DLLINFOLIST_CLASS), null, null); return result; } } private static RList createDLLInfoList(Object[] data) { RList dllInfo = RDataFactory.createList(data, RDataFactory.createStringVector(DLLInfo.NAMES, RDataFactory.COMPLETE_VECTOR)); - RVector.setClassAttr(dllInfo, RDataFactory.createStringVectorFromScalar(DLLINFO_CLASS), null, null); + RVector.setVectorClassAttr(dllInfo, RDataFactory.createStringVectorFromScalar(DLLINFO_CLASS), null, null); return dllInfo; } 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 41bb9c8adaf5989b8d7c706ea9a6a388d170e6b7..2d12a2bf032f27e981b2060119c56c7daf82bec4 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 @@ -32,7 +32,7 @@ import com.oracle.truffle.api.utilities.*; 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.utils.CountFields; +import com.oracle.truffle.r.nodes.builtin.utils.*; import com.oracle.truffle.r.nodes.unary.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.RError.Message; @@ -579,13 +579,15 @@ 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)) { + Object conArg = argValues[1]; + RConnection con; + if (!(conArg instanceof RConnection)) { throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, "'file' is not a connection"); + } else { + con = (RConnection) conArg; } // TODO check connection writeable @@ -599,10 +601,10 @@ public class ForeignFunctions { Object quoteArg = argValues[9]; byte qmethod = castLogical(frame, argValues[10]); - String sep; - String eol; - String na; - String dec; + String csep; + String ceol; + String cna; + String cdec; if (nr == RRuntime.INT_NA) { invalidArgument("nr"); @@ -613,25 +615,24 @@ public class ForeignFunctions { if (!(rnamesArg instanceof RNull) && isString(rnamesArg) == null) { invalidArgument("rnames"); } - if ((sep = isString(sepArg)) == null) { + if ((csep = isString(sepArg)) == null) { invalidArgument("sep"); } - if ((eol = isString(eolArg)) == null) { + if ((ceol = isString(eolArg)) == null) { invalidArgument("eol"); } - if ((na = isString(naArg)) == null) { + if ((cna = isString(naArg)) == null) { invalidArgument("na"); } - if ((dec = isString(decArg)) == null) { + if ((cdec = isString(decArg)) == null) { invalidArgument("dec"); } if (qmethod == RRuntime.LOGICAL_NA) { invalidArgument("qmethod"); } - if (dec.length() != 1) { + if (cdec.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; @@ -644,7 +645,11 @@ public class ForeignFunctions { quoteCol[qi - 1] = true; } } - // TODO call WriteTable + try { + WriteTable.execute(con, argValues[0], nr, nc, rnamesArg, csep, ceol, cna, cdec.charAt(0), RRuntime.fromLogical(qmethod), quoteCol, quoteRn); + } catch (IOException | IllegalArgumentException ex) { + throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, ex.getMessage()); + } return RNull.instance; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java index 4e0c8e5e25433a92d32f1b0669163d473dfa49c2..47f8b92b2b92b5a5c3420239ccefb013027ed43b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java @@ -167,7 +167,7 @@ public abstract class Format extends RBuiltinNode { @SuppressWarnings("unused") @Specialization(guards = "!wrongArgs") - protected RStringVector format(VirtualFrame frame, RAbstractIntVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, + protected RStringVector format(RAbstractIntVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec, RAbstractVector sciVec) { if (value.getLength() == 0) { return RDataFactory.createEmptyStringVector(); @@ -248,12 +248,18 @@ public abstract class Format extends RBuiltinNode { @SuppressWarnings("unused") @Specialization(guards = "!wrongArgs") - protected RStringVector format(VirtualFrame frame, RStringVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, - RLogicalVector naEncodeVec, RAbstractVector sciVec) { + protected RStringVector format(RStringVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec, + RAbstractVector sciVec) { // TODO: implement full semantics return value; } + @Specialization(guards = "!wrongArgs") + protected RStringVector format(RFactor value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec, + RAbstractVector sciVec) { + return format(value.getVector(), trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec); + } + // TruffleDSL bug - should not need multiple guards here protected boolean wrongArgsObject(@SuppressWarnings("unused") Object value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec, RAbstractVector sciVec) { @@ -288,7 +294,7 @@ public abstract class Format extends RBuiltinNode { return false; } - protected boolean wrongArgs(RAbstractVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec, + protected boolean wrongArgs(RAbstractContainer value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec, RAbstractVector sciVec) { return wrongArgsObject(value, trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java index c330411359b5db4de315d1ba6a4c29e9ab5f8746..da6df56c0b4dc1fc8301e55993735d543742594d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java @@ -146,4 +146,10 @@ public abstract class IsNA extends RBuiltinNode { controlVisibility(); return RRuntime.LOGICAL_FALSE; } + + @Specialization + protected RLogicalVector isNA(RFactor value) { + return isNA(value.getVector()); + } + } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java index 89570da0f4624a0ad412da55b5e2060c53430803..4af928c4d319c21e85eca9135fe9c3e32b469b52 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java @@ -103,6 +103,12 @@ public class IsTypeFunctions { return arg.getElementClass() == Object.class; } + @Specialization + protected byte isAtomic(RFactor arg) { + controlVisibility(); + return RRuntime.LOGICAL_TRUE; + } + } @RBuiltin(name = "is.call", kind = PRIMITIVE, parameterNames = {"x"}) diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java index efa2d560ffd323ac0cb5ded1a4fdb5334c039087..9edbd53f30eb6535a8aad7e37eed72c8a606666b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java @@ -314,7 +314,7 @@ public class LaFunctions { RDoubleVector modulusVec = RDataFactory.createDoubleVectorFromScalar(modulus); modulusVec.setAttr("logarithm", useLogIn); RList result = RDataFactory.createList(new Object[]{modulusVec, sign}, NAMES_VECTOR); - RList.setClassAttr(result, DET_CLASS, null, null); + RList.setVectorClassAttr(result, DET_CLASS, null, null); return result; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java index a00d5102dd3a9386c0615a6753b68289a2af50df..bf38632c7ca1036932c027556fdbc3bbcda67bde 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java @@ -24,9 +24,12 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.runtime.RBuiltinKind.*; +import java.util.function.*; + import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.utilities.*; import com.oracle.truffle.r.nodes.*; import com.oracle.truffle.r.nodes.access.*; import com.oracle.truffle.r.nodes.builtin.*; @@ -38,42 +41,104 @@ import com.oracle.truffle.r.runtime.data.RPromise.PromiseProfile; @RBuiltin(name = "missing", kind = PRIMITIVE, parameterNames = {"x"}, nonEvalArgs = {0}) public abstract class Missing extends RBuiltinNode { - private final PromiseProfile promiseProfile = new PromiseProfile(); + @Child private InlineCacheNode<Frame, Symbol> repCache; - @Child private GetMissingValueNode getMissingValue; + private final ConditionProfile isSymbolNullProfile = ConditionProfile.createBinaryProfile(); - @Specialization - protected byte missing(VirtualFrame frame, RPromise promise) { - controlVisibility(); - // Unwrap current promise, as it's irrelevant for 'missing' - RNode argExpr = (RNode) promise.getRep(); - Symbol symbol = RMissingHelper.unwrapSymbol(argExpr); + private static InlineCacheNode<Frame, Symbol> createRepCache(int level) { + Function<Symbol, RNode> reify = symbol -> createNodeForRep(symbol, level); + BiFunction<Frame, Symbol, Object> generic = (frame, symbol) -> RRuntime.asLogical(RMissingHelper.isMissingArgument(frame, symbol)); + return InlineCacheNode.create(3, reify, generic); + } + + private static RNode createNodeForRep(Symbol symbol, int level) { if (symbol == null) { - return RRuntime.asLogical(false); + return ConstantNode.create(RRuntime.LOGICAL_FALSE); } + return new MissingCheckLevel(symbol, level); + } - // Read symbols value directly - if (getMissingValue == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - getMissingValue = insert(GetMissingValueNode.create(symbol)); + private static class MissingCheckLevel extends RNode { + + @Child private GetMissingValueNode getMissingValue; + @Child private InlineCacheNode<Frame, Symbol> recursive; + + private final ConditionProfile isNullProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile isMissingProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile isPromiseProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile isSymbolNullProfile = ConditionProfile.createBinaryProfile(); + private final PromiseProfile promiseProfile = new PromiseProfile(); + private final int level; + + public MissingCheckLevel(Symbol symbol, int level) { + this.level = level; + this.getMissingValue = GetMissingValueNode.create(symbol); } - Object obj = getMissingValue.execute(frame); - if (obj == null) { - // In case we are not able to read the symbol in current frame: This is not an argument - // and thus return false - return RRuntime.asLogical(false); + + @Override + public Object execute(VirtualFrame frame) { + // Read symbols value directly + Object value = getMissingValue.execute(frame); + if (isNullProfile.profile(value == null)) { + // In case we are not able to read the symbol in current frame: This is not an + // argument and thus return false + return RRuntime.LOGICAL_FALSE; + } + + if (isMissingProfile.profile(value == RMissing.instance)) { + return RRuntime.LOGICAL_TRUE; + } + + assert level < 30; + // This might be a promise... + if (isPromiseProfile.profile(value instanceof RPromise)) { + RPromise promise = (RPromise) value; + if (level == 0 && promise.isDefault(promiseProfile)) { + return RRuntime.LOGICAL_TRUE; + } + if (level > 0 && promise.isEvaluated(promiseProfile)) { + return RRuntime.LOGICAL_FALSE; + } + if (recursive == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + recursive = insert(createRepCache(level + 1)); + } + // Check: If there is a cycle, return true. (This is done like in GNU R) + if (promise.isUnderEvaluation(promiseProfile)) { + return RRuntime.LOGICAL_TRUE; + } + try { + promise.setUnderEvaluation(true); + Symbol symbol = RMissingHelper.unwrapSymbol((RNode) promise.getRep()); + return isSymbolNullProfile.profile(symbol == null) ? RRuntime.LOGICAL_FALSE : recursive.execute(promise.getFrame(), symbol); + } finally { + promise.setUnderEvaluation(false); + } + } + return RRuntime.LOGICAL_FALSE; } + } - return RRuntime.asLogical(RMissingHelper.isMissing(obj, promiseProfile)); + @Specialization + protected byte missing(VirtualFrame frame, RPromise promise) { + controlVisibility(); + if (repCache == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + repCache = insert(createRepCache(0)); + } + Symbol symbol = RMissingHelper.unwrapSymbol((RNode) promise.getRep()); + return isSymbolNullProfile.profile(symbol == null) ? RRuntime.LOGICAL_FALSE : (byte) repCache.execute(frame, symbol); } - @Specialization(guards = "!isPromise") - protected byte missing(Object obj) { + @Specialization + protected byte missing(@SuppressWarnings("unused") RMissing obj) { controlVisibility(); - return RRuntime.asLogical(RMissingHelper.isMissing(obj, promiseProfile)); + return RRuntime.LOGICAL_TRUE; } - public boolean isPromise(Object obj) { - return obj instanceof RPromise; + @Fallback + protected byte missing(@SuppressWarnings("unused") Object obj) { + controlVisibility(); + return RRuntime.LOGICAL_FALSE; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java index 96e572bfb2d7240a1f682721b6891c3f71f99304..cd3c4edb7128191dc8ae56b02746bb653aaaf063 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java @@ -28,6 +28,7 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.Node.*; import com.oracle.truffle.api.source.*; import com.oracle.truffle.r.nodes.*; import com.oracle.truffle.r.nodes.access.ConstantNode; @@ -41,8 +42,10 @@ import com.oracle.truffle.r.nodes.function.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; +import com.oracle.truffle.r.runtime.data.closures.*; import com.oracle.truffle.r.runtime.data.model.*; import com.oracle.truffle.r.runtime.env.*; +import com.oracle.truffle.r.runtime.ops.na.*; @SuppressWarnings("unused") @NodeChildren({@NodeChild(value = "operand", type = RNode.class), @NodeChild(value = "listElementName", type = RNode.class), @NodeChild(value = "quote", type = RNode.class), @@ -518,9 +521,13 @@ public abstract class PrettyPrinterNode extends RNode { resultBuilder.append(vector.getLength() - maxPrint); resultBuilder.append(" entries ]"); } - RAttributes attributes = vector.getAttributes(); - if (attributes != null) { - resultBuilder.append(printAttributes(vector, attributes)); + if (!(vector instanceof RFactorToStringVectorClosure)) { + // it's a bit of a hack, but factors are meant to be printed using the S3 function + // anyway - the idea is to suppress attribute printing for factors nested in lists + RAttributes attributes = vector.getAttributes(); + if (attributes != null) { + resultBuilder.append(printAttributes(vector, attributes)); + } } return builderToString(resultBuilder); } @@ -1014,6 +1021,8 @@ public abstract class PrettyPrinterNode extends RNode { @Child private PrettyPrinterNode prettyPrinter; + private final NACheck naCheck = NACheck.create(); + private void initCast(Object listElementName) { if (prettyPrinter == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -1121,6 +1130,27 @@ public abstract class PrettyPrinterNode extends RNode { return prettyPrintSingleElement(operand, listElementName, quote, right); } + // TODO: this should be handled by an S3 function + @TruffleBoundary + @Specialization + protected String prettyPrintListElement(RFactor operand, Object listElementName, byte quote, byte right) { + StringBuilder sb = new StringBuilder(prettyPrintSingleElement(RClosures.createFactorToStringVector(operand, naCheck), listElementName, RRuntime.LOGICAL_FALSE, right)); + sb.append("\nLevels:"); + Object attr = operand.getVector().getAttr(RRuntime.LEVELS_ATTR_KEY); + if (attr != null) { + if (attr instanceof String) { + sb.append(" "); + sb.append(attr.toString()); + } else { + RAbstractStringVector vec = (RAbstractStringVector) attr; + for (int i = 0; i < vec.getLength(); i++) { + sb.append(" "); + sb.append(vec.getDataAt(i)); + } + } + } + return sb.toString(); + } } @NodeChildren({@NodeChild(value = "operand", type = RNode.class), @NodeChild(value = "isQuoted", type = RNode.class)}) diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Structure.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Structure.java index 5b4deb547537bd121ebb92104b211ffc5d50b35e..fcc23b4d159c2eac5ce04b236226bdf2fad83153 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Structure.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Structure.java @@ -75,16 +75,25 @@ public abstract class Structure extends RBuiltinNode { Object[] values = args.getValues(); String[] argNames = getSuppliedArgsNames(); validateArgNames(argNames); + RAbstractContainer res = obj; for (int i = 0; i < values.length; i++) { Object value = fixupValue(values[i]); String attrName = fixupAttrName(argNames[i + 1]); - if (value == RNull.instance) { - obj.removeAttr(attrName); + if (attrName.equals(RRuntime.CLASS_ATTR_KEY)) { + if (value == RNull.instance) { + res = (RAbstractContainer) res.setClassAttr(null); + } else { + res = (RAbstractContainer) res.setClassAttr((RStringVector) value); + } } else { - obj.setAttr(attrName, value); + if (value == RNull.instance) { + res.removeAttr(attrName); + } else { + res.setAttr(attrName, value); + } } } - return obj; + return res; } private Object fixupValue(Object value) { 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 03ef8a58d23cd2fabfa762bd1268775a9ead3f8a..78aa089824addcc4edd5c63a273d83dc567247cc 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,9 +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")); - return RDataFactory.createFactor(res); + res.setLevels(RDataFactory.createStringVector(levelsArray, RDataFactory.COMPLETE_VECTOR)); + return RVector.setVectorClassAttr(res, RDataFactory.createStringVector("factor"), null, null); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java index eb31cd844a3b507e5dbdc44ca31776eb3da61af2..e5cf9deda213d3b50990031152b8629995aad884 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java @@ -35,7 +35,7 @@ public abstract class UnClass extends RBuiltinNode { if (resultVector.isShared()) { resultVector = resultVector.copy(); } - return RVector.setClassAttr(resultVector, null, null, null); + return RVector.setVectorClassAttr(resultVector, null, null, null); } return arg; } @@ -48,7 +48,7 @@ public abstract class UnClass extends RBuiltinNode { if (resultFrame.isShared()) { resultFrame = resultFrame.copy(); } - return RVector.setClassAttr(resultFrame.getVector(), null, arg, null); + return RVector.setVectorClassAttr(resultFrame.getVector(), null, arg, null); } @Specialization @@ -59,6 +59,6 @@ public abstract class UnClass extends RBuiltinNode { if (resultFrame.isShared()) { resultFrame = resultFrame.copy(); } - return RVector.setClassAttr(resultFrame.getVector(), null, null, arg); + return RVector.setVectorClassAttr(resultFrame.getVector(), null, null, arg); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java index 9cc09ec1e4d84395cd5dea0798e1d1c1645ca325..5dc2897803a17a4a35e0067229a1fd98cc115e64 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java @@ -99,7 +99,7 @@ public abstract class UpdateAttr extends RInvisibleBuiltinNode { } else if (name.equals(RRuntime.DIMNAMES_ATTR_KEY)) { return updateDimNames(frame, resultVector, value); } else if (name.equals(RRuntime.CLASS_ATTR_KEY)) { - return RVector.setClassAttr(resultVector, null, container.getElementClass() == RDataFrame.class ? container : null, container.getElementClass() == RFactor.class ? container : null); + return RVector.setVectorClassAttr(resultVector, null, container.getElementClass() == RDataFrame.class ? container : null, container.getElementClass() == RFactor.class ? container : null); } else if (name.equals(RRuntime.ROWNAMES_ATTR_KEY)) { resultVector.setRowNames(null); } else if (name.equals(RRuntime.LEVELS_ATTR_KEY)) { @@ -114,11 +114,11 @@ public abstract class UpdateAttr extends RInvisibleBuiltinNode { @TruffleBoundary public static RAbstractContainer setClassAttrFromObject(RVector resultVector, RAbstractContainer container, Object value, SourceSection sourceSection) { if (value instanceof RStringVector) { - return RVector.setClassAttr(resultVector, (RStringVector) value, container.getElementClass() == RDataFrame.class ? container : null, + return RVector.setVectorClassAttr(resultVector, (RStringVector) value, container.getElementClass() == RDataFrame.class ? container : null, container.getElementClass() == RFactor.class ? container : null); } if (value instanceof String) { - return RVector.setClassAttr(resultVector, RDataFactory.createStringVector((String) value), container.getElementClass() == RDataFrame.class ? container : null, + return RVector.setVectorClassAttr(resultVector, RDataFactory.createStringVector((String) value), container.getElementClass() == RDataFrame.class ? container : null, container.getElementClass() == RFactor.class ? container : null); } throw RError.error(sourceSection, RError.Message.SET_INVALID_CLASS_ATTR); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java index e057dd8e85058fa8143487c7c56b1901aef861b5..1026beea51f893fae726a59c2c250392da7d0f44 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java @@ -89,7 +89,7 @@ public abstract class UpdateAttributes extends RInvisibleBuiltinNode { } @Specialization - protected RAbstractVector updateAttributes(VirtualFrame frame, RAbstractContainer container, RList list) { + protected RAbstractContainer updateAttributes(VirtualFrame frame, RAbstractContainer container, RList list) { controlVisibility(); Object listNamesObject = list.getNames(); if (listNamesObject == null || listNamesObject == RNull.instance) { @@ -97,6 +97,7 @@ public abstract class UpdateAttributes extends RInvisibleBuiltinNode { } RStringVector listNames = (RStringVector) listNamesObject; RVector resultVector = container.materializeNonSharedVector(); + RAbstractContainer res = resultVector; if (numAttributesProfile.profile(list.getLength() == 0)) { resultVector.resetAllAttributes(true); } else { @@ -113,9 +114,9 @@ public abstract class UpdateAttributes extends RInvisibleBuiltinNode { // set the dim attribute first setDimAttribute(frame, resultVector, list); // set the remaining attributes in order - setRemainingAttributes(frame, container, resultVector, list); + res = setRemainingAttributes(frame, container, resultVector, list); } - return resultVector; + return res; } @TruffleBoundary @@ -155,10 +156,11 @@ public abstract class UpdateAttributes extends RInvisibleBuiltinNode { } @ExplodeLoop - private void setRemainingAttributes(VirtualFrame virtualFrame, RAbstractContainer container, RVector resultVector, RList sourceList) { + private RAbstractContainer setRemainingAttributes(VirtualFrame virtualFrame, RAbstractContainer container, RVector resultVector, RList sourceList) { RStringVector listNames = (RStringVector) sourceList.getNames(); int length = sourceList.getLength(); assert length > 0 : "Length should be > 0 for ExplodeLoop"; + RAbstractContainer res = resultVector; for (int i = 0; i < sourceList.getLength(); i++) { Object value = sourceList.getDataAt(i); String attrName = listNames.getDataAt(i); @@ -174,9 +176,9 @@ public abstract class UpdateAttributes extends RInvisibleBuiltinNode { } } else if (attrName.equals(RRuntime.CLASS_ATTR_KEY)) { if (value == RNull.instance) { - RVector.setClassAttr(resultVector, null, container.getElementClass() == RDataFrame.class ? container : null, container.getElementClass() == RFactor.class ? container : null); + res = RVector.setVectorClassAttr(resultVector, null, container.getElementClass() == RDataFrame.class ? container : null, container.getElementClass() == RFactor.class ? container : null); } else { - UpdateAttr.setClassAttrFromObject(resultVector, container, value, getEncapsulatingSourceSection()); + res = UpdateAttr.setClassAttrFromObject(resultVector, container, value, getEncapsulatingSourceSection()); } } else if (attrName.equals(RRuntime.ROWNAMES_ATTR_KEY)) { resultVector.setRowNames(castVector(virtualFrame, value)); @@ -190,6 +192,7 @@ public abstract class UpdateAttributes extends RInvisibleBuiltinNode { } } } + return res; } @Fallback diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java index b3675f366db369c158ec27d7f1b2bf98afc7e8bc..37fa0e9d465ea96cd68cb0f540b5e68ec3131a63 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java @@ -61,7 +61,7 @@ public abstract class UpdateClass extends RBuiltinNode { protected Object setClass(RAbstractContainer arg, @SuppressWarnings("unused") RNull className) { controlVisibility(); RVector resultVector = arg.materializeNonSharedVector(); - return RVector.setClassAttr(resultVector, null, arg.getElementClass() == RDataFrame.class ? arg : null, arg.getElementClass() == RFactor.class ? arg : null); + return RVector.setVectorClassAttr(resultVector, null, arg.getElementClass() == RDataFrame.class ? arg : null, arg.getElementClass() == RFactor.class ? arg : null); } @Specialization @@ -102,7 +102,7 @@ public abstract class UpdateClass extends RBuiltinNode { throw RError.error(getEncapsulatingSourceSection(), RError.Message.NOT_ARRAY_UPDATE_CLASS); } - return RVector.setClassAttr(resultVector, RDataFactory.createStringVector(className), arg.getElementClass() == RDataFrame.class ? arg : null, arg.getElementClass() == RFactor.class ? arg + return RVector.setVectorClassAttr(resultVector, RDataFactory.createStringVector(className), arg.getElementClass() == RDataFrame.class ? arg : null, arg.getElementClass() == RFactor.class ? arg : null); } @@ -111,7 +111,7 @@ public abstract class UpdateClass extends RBuiltinNode { protected Object setClass(RAbstractContainer arg, RStringVector className) { controlVisibility(); RVector resultVector = arg.materializeNonSharedVector(); - return RVector.setClassAttr(resultVector, className, arg.getElementClass() == RDataFrame.class ? arg : null, arg.getElementClass() == RFactor.class ? arg : null); + return RVector.setVectorClassAttr(resultVector, className, arg.getElementClass() == RDataFrame.class ? arg : null, arg.getElementClass() == RFactor.class ? arg : null); } public Object setClass(RFunction arg, @SuppressWarnings("unused") Object className) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java index c9d49853b917dadec1fc28443c79387dd7185d5e..bda5ebe634a64bbaaee2959a01c772c0840c4129 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java @@ -76,7 +76,7 @@ public abstract class UpdateOldClass extends RInvisibleBuiltinNode { protected Object setOldClass(RAbstractContainer arg, RStringVector className) { controlVisibility(); RVector resultVector = arg.materializeNonSharedVector(); - return RVector.setClassAttr(resultVector, className, arg.getElementClass() == RDataFrame.class ? arg : null, arg.getElementClass() == RFactor.class ? arg : null); + return RVector.setVectorClassAttr(resultVector, className, arg.getElementClass() == RDataFrame.class ? arg : null, arg.getElementClass() == RFactor.class ? arg : null); } @Specialization @@ -84,7 +84,7 @@ public abstract class UpdateOldClass extends RInvisibleBuiltinNode { protected Object setOldClass(RAbstractContainer arg, @SuppressWarnings("unused") RNull className) { controlVisibility(); RVector resultVector = arg.materializeNonSharedVector(); - return RVector.setClassAttr(resultVector, null, arg.getElementClass() == RDataFrame.class ? arg : null, arg.getElementClass() == RFactor.class ? arg : null); + return RVector.setVectorClassAttr(resultVector, null, arg.getElementClass() == RDataFrame.class ? arg : null, arg.getElementClass() == RFactor.class ? arg : null); } @TruffleBoundary diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java index 200ede3e97bf0f1721c4ff94b64261702a39600a..480169c013a924a88259accdc8287cd4048fb1a9 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java @@ -64,7 +64,17 @@ public abstract class UpdateStorageMode extends RBuiltinNode { if (attrs != null) { RAttributable rresult = (RAttributable) result; for (RAttribute attr : attrs) { - rresult.setAttr(attr.getName(), attr.getValue()); + String attrName = attr.getName(); + Object v = attr.getValue(); + if (attrName.equals(RRuntime.CLASS_ATTR_KEY)) { + if (v == RNull.instance) { + rresult = rresult.setClassAttr(null); + } else { + rresult = rresult.setClassAttr((RStringVector) v); + } + } else { + rresult.setAttr(attrName, v); + } } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java index dc2afb7fbf7a5cce07af04b5024a4947ccebcc3e..23fdfd3d6b48b615ceceec9dfd41c45baa0b85c9 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java @@ -15,6 +15,7 @@ import static com.oracle.truffle.r.runtime.RBuiltinKind.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.r.nodes.*; import com.oracle.truffle.r.nodes.access.*; import com.oracle.truffle.r.nodes.builtin.*; @@ -87,6 +88,7 @@ public abstract class UseMethod extends RBuiltinNode { } } + @NodeInfo(cost = NodeCost.UNINITIALIZED) private static final class UninitializedUseMethodNode extends UseMethodNode { protected final int depth; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java index ee32d4b062fadb17d7d596c269dce3e39d15f781..5395974b3fdf0e9df8b8f302dbeb8bb70f4f03d1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java @@ -47,12 +47,12 @@ import static com.oracle.truffle.r.runtime.RBuiltinKind.INTERNAL; */ public class WhichFunctions { - @RBuiltin(name = "which", kind = INTERNAL, parameterNames = {"x", "arr.ind", "useNames"}) + @RBuiltin(name = "which", kind = INTERNAL, parameterNames = {"x"}) public abstract static class Which extends RBuiltinNode { @Override public RNode[] getParameterValues() { - return new RNode[]{ConstantNode.create(RMissing.instance), ConstantNode.create(RRuntime.LOGICAL_FALSE), ConstantNode.create(RRuntime.LOGICAL_TRUE)}; + return new RNode[]{ConstantNode.create(RMissing.instance)}; } @Specialization @@ -69,7 +69,7 @@ public class WhichFunctions { for (int i = 0; i < result.length; ++i) { result[i] = w.get(i) + 1; } - return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR); + return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR, x.getNames()); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/UtilsPackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/UtilsPackage.java index cec62105707b90d71030ad92ee9012dcddc8242a..17c80f02362ccbc7127038dad606ef06d7ea06bd 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/UtilsPackage.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/UtilsPackage.java @@ -1,12 +1,24 @@ /* - * This material is distributed under the GNU General Public License - * Version 2. You may review the terms of this license at - * http://www.gnu.org/licenses/gpl-2.0.html + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Copyright (c) 2014, Purdue University - * Copyright (c) 2014, Oracle and/or its affiliates + * 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. * - * All rights reserved. + * 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.nodes.builtin.utils; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/WriteTable.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/WriteTable.java new file mode 100644 index 0000000000000000000000000000000000000000..b842fb3814ac9f458cf4a610f5b556a4c43e0dd7 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/WriteTable.java @@ -0,0 +1,165 @@ +/* + * This material is distributed under the GNU General Public License + * Version 2. You may review the terms of this license at + * http://www.gnu.org/licenses/gpl-2.0.html + * + * Copyright (c) 1995-2012, The R Core Team + * Copyright (c) 2003, The R Foundation + * Copyright (c) 2014, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.nodes.builtin.utils; + +import java.io.*; + +import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.model.*; + +//Transcribed from GnuR, library/utils/src/io.c + +//Checkstyle: stop +public class WriteTable { + // @formatter:off + public static Object execute(RConnection con, Object xx, int nr, int nc, Object rnames, String csep, String ceol, String cna, + char cdec, boolean qmethod, boolean[] quoteCol, boolean quoteRn) throws IOException, IllegalArgumentException { + // @formatter:on + OutputStream os = con.getOutputStream(); + String tmp = null; + if (xx instanceof RDataFrame) { /* A data frame */ + RVector xy = ((RDataFrame) xx).getVector(); + RVector x = (RVector) xy.getDataAtAsObject(0); + + /* handle factors internally, check integrity */ + RStringVector[] levels = new RStringVector[nc]; + for (int j = 0; j < nc; j++) { + RAbstractContainer xj = (RAbstractContainer) x.getDataAtAsObject(j); + if (xj.getLength() != nr) { + throw new IllegalArgumentException("corrupt data frame -- length of column " + (j + 1) + " does not not match nrows"); + } + if (isFactor(xj)) { + levels[j] = (RStringVector) xj.getAttributes().get("levels"); + } + } + + for (int i = 0; i < nr; i++) { + // if (i % 1000 == 999) + // R_CheckUserInterrupt(); + if (!(rnames instanceof RNull)) { + os.write(encodeElement2((RStringVector) rnames, i, quoteRn, qmethod, cdec).getBytes()); + os.write(csep.getBytes()); + } + for (int j = 0; j < nc; j++) { + RAbstractContainer xj = (RAbstractContainer) x.getDataAtAsObject(j); + if (j > 0) + os.write(csep.getBytes()); + if (isna(xj, i)) { + tmp = cna; + } else { + if (levels[j] != null) { + tmp = encodeElement2(levels[j], (int) xj.getDataAtAsObject(i) - 1, quoteCol[j], qmethod, cdec); + } else { + tmp = encodeElement2((RAbstractVector) xj, i, quoteCol[j], qmethod, cdec); + } + /* if(cdec) change_dec(tmp, cdec, TYPEOF(xj)); */ + } + os.write(tmp.getBytes()); + } + os.write(ceol.getBytes()); + } + + } else { /* A matrix */ + + // if (!isVectorAtomic(x)) + // UNIMPLEMENTED_TYPE("write.table, matrix method", x); + RVector x = (RVector) xx; + /* quick integrity check */ + if (x.getLength() != nr * nc) { + throw new IllegalArgumentException("corrupt matrix -- dims not not match length"); + } + + for (int i = 0; i < nr; i++) { + if (i % 1000 == 999) { + // R_CheckUserInterrupt(); + } + if (!(rnames instanceof RNull)) { + os.write(encodeElement2((RStringVector) rnames, i, quoteRn, qmethod, cdec).getBytes()); + os.write(csep.getBytes()); + } + for (int j = 0; j < nc; j++) { + if (j > 0) { + os.write(csep.getBytes()); + } + if (isna(x, i + j * nr)) { + tmp = cna; + } else { + tmp = encodeElement2(x, i + j * nr, quoteCol[j], qmethod, cdec); + /* if(cdec) change_dec(tmp, cdec, TYPEOF(x)); */ + } + os.write(tmp.getBytes()); + } + os.write(ceol.getBytes()); + } + + } + return RNull.instance; + } + + /* a version of EncodeElement with different escaping of char strings */ + private static String encodeElement2(RAbstractVector x, int indx, boolean quote, boolean qmethod, char cdec) { + if (indx < 0 || indx >= x.getLength()) { + throw new IllegalArgumentException("index out of range"); + } + if (x instanceof RStringVector) { + RStringVector sx = (RStringVector) x; + StringBuffer sb = new StringBuffer(); + String p0 = /* translateChar */sx.getDataAt(indx); + if (!quote) + return p0; + sb.append('"'); + for (int i = 0; i < p0.length(); i++) { + char p = p0.charAt(i); + if (p == '"') { + sb.append(qmethod ? '\\' : '"'); + } + sb.append(p); + } + sb.append('"'); + return sb.toString(); + } + return encodeElement(x, indx, quote ? '"' : 0, cdec); + } + + private static boolean isna(RAbstractContainer x, int indx) { + if (x instanceof RLogicalVector) { + return RRuntime.isNA(((RLogicalVector) x).getDataAt(indx)); + } else if (x instanceof RDoubleVector) { + return RRuntime.isNA(((RDoubleVector) x).getDataAt(indx)); + } else if (x instanceof RIntVector) { + return RRuntime.isNA(((RIntVector) x).getDataAt(indx)); + } else if (x instanceof RStringVector) { + return RRuntime.isNA(((RStringVector) x).getDataAt(indx)); + } else if (x instanceof RComplexVector) { + RComplexVector cvec = (RComplexVector) x; + RComplex c = cvec.getDataAt(indx); + return c.isNA(); + } else { + return false; + } + } + + @SuppressWarnings("unused") + private static String encodeElement(Object x, int indx, char quote, char dec) { + throw RInternalError.unimplemented(); + } + + private static boolean isFactor(RAbstractContainer v) { + for (int i = 0; i < v.getClassHierarchy().getLength(); i++) { + if (v.getClassHierarchy().getDataAt(i).equals("factor")) { + return true; + } + } + return false; + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/CallInlineCacheNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/CallInlineCacheNode.java index f8f7fff1860d11c0ee70b63ad6234d0ac2e035f2..6ebcf6cbb962f8edf51c26d98b8eb60cf069339d 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/CallInlineCacheNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/CallInlineCacheNode.java @@ -45,6 +45,7 @@ public abstract class CallInlineCacheNode extends Node { return new UninitializedCallInlineCacheNode(maxPicDepth); } + @NodeInfo(cost = NodeCost.UNINITIALIZED) private static final class UninitializedCallInlineCacheNode extends CallInlineCacheNode { private final int maxPicDepth; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/InlineCacheNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/InlineCacheNode.java index f490925043f3a64b033c7db61d163746d5f9724f..f80ceb6a9f9b8f28018adceabe8ebe8c077e8062 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/InlineCacheNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/InlineCacheNode.java @@ -74,6 +74,7 @@ public abstract class InlineCacheNode<F extends Frame, T> extends Node { return create(maxPicDepth, closure -> (RNode) closure.getExpr(), (frame, closure) -> RContext.getEngine().evalPromise(closure, frame.materialize())); } + @NodeInfo(cost = NodeCost.UNINITIALIZED) private static final class UninitializedInlineCacheNode<F extends Frame, T> extends InlineCacheNode<F, T> { private final int maxPicDepth; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java index 0f88a96422ac34b27c4c18862f6d8557869bb061..2b12522378a4dc8363781d2d9e1375fd959629ea 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java @@ -67,6 +67,7 @@ public abstract class FrameSlotNode extends Node { return new PresentFrameSlotNode(slot); } + @NodeInfo(cost = NodeCost.UNINITIALIZED) private static final class UnresolvedFrameSlotNode extends FrameSlotNode { private final Object identifier; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariableNode.java index 411c469e4a26860f6a418d598179fb717b6b8dbd..4f8dce9a8b1775a9f5754680b6e44521a0253c0f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariableNode.java @@ -278,6 +278,7 @@ public abstract class ReadVariableNode extends RNode implements VisibilityContro RType getMode(); } + @NodeInfo(cost = NodeCost.UNINITIALIZED) public static final class UnresolvedReadVariableNode extends ReadVariableNode implements HasMode { // TODO It seems a refactoring would be appropriate to encapsulate all fields (symbol, mode, @@ -460,6 +461,7 @@ public abstract class ReadVariableNode extends RNode implements VisibilityContro } } + @NodeInfo(cost = NodeCost.UNINITIALIZED) public static final class UnResolvedReadLocalVariableNode extends ReadVariableNode implements HasMode { private final Symbol symbol; private final RType mode; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java index b322e5d520d2c0f63d18388948b44e326808d047..b459fcff3dd6929beb88f672908c4a2ff0ed6485 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java @@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.access; import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; import com.oracle.truffle.api.utilities.*; import com.oracle.truffle.r.nodes.*; @@ -152,6 +153,7 @@ public abstract class WriteVariableNode extends RNode implements VisibilityContr public abstract void execute(VirtualFrame frame, Object value); + @NodeInfo(cost = NodeCost.UNINITIALIZED) @NodeFields({@NodeField(name = "name", type = String.class), @NodeField(name = "mode", type = Mode.class)}) public abstract static class UnresolvedWriteLocalVariableNode extends WriteVariableNode { 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 e853324fdf9307d15d45f1701ce9d49c36b16723..42cc3f0d73727ff0f766e5231a30dc66ca76f5c1 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,14 @@ 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)); + return RVector.setVectorClassAttr(res, RDataFactory.createStringVector("factor"), null, null); + } + @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 eec8bfc66da0e9e94c01b80404bb1c5bad7d1e68..d6d5c8f5ea150b6d87162d763660e75cd61573a9 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 6a1cfd0c93db3532420a91ca67ee01e3931542c6..5892d9d53419ddd74bc4e36e537f3247295285d3 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) { @@ -178,6 +193,17 @@ public abstract class UpdateArrayHelperNode extends RNode { } @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(guards = "isSubset") 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/binary/BinaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java index 3b2e1647c639918a561c3c1d97aafa85331bdc0f..ca31defef717cb4c7268e3c49f94a3b39e86a222 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java @@ -88,6 +88,28 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode { return specializeToUnaryOp().execute(frame, left); } + @Specialization + protected RLogicalVector doFactorOp(RFactor left, @SuppressWarnings("unused") RNull right) { + if (left.isOrdered()) { + RError.warning(getEncapsulatingSourceSection(), RError.Message.NOT_MEANINGFUL_FOR_ORDERED_FACTORS, arithmetic.opName()); + + } else { + RError.warning(getEncapsulatingSourceSection(), RError.Message.NOT_MEANINGFUL_FOR_FACTORS, arithmetic.opName()); + } + return RDataFactory.createNAVector(left.getLength() == 0 ? 1 : left.getLength()); + } + + @Specialization + protected RLogicalVector doFactorOp(@SuppressWarnings("unused") RNull left, RFactor right) { + if (right.isOrdered()) { + RError.warning(getEncapsulatingSourceSection(), RError.Message.NOT_MEANINGFUL_FOR_ORDERED_FACTORS, arithmetic.opName()); + + } else { + RError.warning(getEncapsulatingSourceSection(), RError.Message.NOT_MEANINGFUL_FOR_FACTORS, arithmetic.opName()); + } + return RDataFactory.createNAVector(right.getLength() == 0 ? 1 : right.getLength()); + } + @Specialization protected RDoubleVector doLeftNull(RNull left, RAbstractIntVector right) { return doRightNull(right, left); @@ -103,6 +125,12 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode { return doRightNull(right, left); } + @SuppressWarnings("unused") + @Specialization(guards = "nonNumeric") + protected RComplexVector doLeftNull(RNull left, RAbstractVector right) { + throw RError.error(this.getSourceSection(), RError.Message.NON_NUMERIC_BINARY); + } + @Specialization protected RComplexVector doLeftNull(RNull left, RAbstractComplexVector right) { return doRightNull(right, left); @@ -132,31 +160,37 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode { return RDataFactory.createEmptyComplexVector(); } + @SuppressWarnings("unused") + @Specialization(guards = "nonNumeric") + protected RComplexVector doRightNull(RAbstractVector left, RNull right) { + throw RError.error(this.getSourceSection(), RError.Message.NON_NUMERIC_BINARY); + } + @SuppressWarnings("unused") @Specialization protected RDoubleVector doRightNull(RNull left, RNull right) { return RDataFactory.createEmptyDoubleVector(); } - @Specialization - protected Object doLeftString(RAbstractStringVector left, Object right) { + @Specialization(guards = "!isFactorRight") + protected Object doLeftString(RAbstractStringVector left, RAbstractContainer right) { return doRightString(right, left); } @SuppressWarnings("unused") - @Specialization - protected Object doRightString(Object left, RAbstractStringVector right) { + @Specialization(guards = "!isFactorLeft") + protected Object doRightString(RAbstractContainer left, RAbstractStringVector right) { throw RError.error(this.getSourceSection(), RError.Message.NON_NUMERIC_BINARY); } - @Specialization - protected Object doLeftRaw(RAbstractRawVector left, Object right) { + @Specialization(guards = "!isFactorRight") + protected Object doLeftRaw(RAbstractRawVector left, RAbstractContainer right) { return doRightRaw(right, left); } @SuppressWarnings("unused") - @Specialization - protected Object doRightRaw(Object left, RAbstractRawVector right) { + @Specialization(guards = "!isFactorLeft") + protected Object doRightRaw(RAbstractContainer left, RAbstractRawVector right) { throw RError.error(this.getSourceSection(), RError.Message.NON_NUMERIC_BINARY); } @@ -490,6 +524,50 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode { return performComplexVectorOpSameLength(left, right); } + // factors + + @Specialization + protected RLogicalVector doFactorOp(RFactor left, RAbstractContainer right) { + if (left.isOrdered()) { + RError.warning(getEncapsulatingSourceSection(), RError.Message.NOT_MEANINGFUL_FOR_ORDERED_FACTORS, arithmetic.opName()); + + } else { + RError.warning(getEncapsulatingSourceSection(), RError.Message.NOT_MEANINGFUL_FOR_FACTORS, arithmetic.opName()); + } + return RDataFactory.createNAVector(Math.max(left.getLength(), right.getLength())); + } + + @Specialization + protected RLogicalVector doFactorOp(RAbstractContainer left, RFactor right) { + if (right.isOrdered()) { + RError.warning(getEncapsulatingSourceSection(), RError.Message.NOT_MEANINGFUL_FOR_ORDERED_FACTORS, arithmetic.opName()); + + } else { + RError.warning(getEncapsulatingSourceSection(), RError.Message.NOT_MEANINGFUL_FOR_FACTORS, arithmetic.opName()); + } + return RDataFactory.createNAVector(Math.max(left.getLength(), right.getLength())); + } + + protected boolean nonNumeric(@SuppressWarnings("unused") RNull left, RAbstractContainer right) { + return right.getElementClass() == RString.class || right.getElementClass() == RRaw.class; + } + + protected boolean nonNumeric(RAbstractContainer left) { + return left.getElementClass() == RString.class || left.getElementClass() == RRaw.class; + } + + protected boolean isFactorLeft(RAbstractContainer left) { + return left.getElementClass() == RFactor.class; + } + + protected boolean isFactorRight(@SuppressWarnings("unused") RAbstractStringVector left, RAbstractContainer right) { + return right.getElementClass() == RFactor.class; + } + + protected boolean isFactorRight(@SuppressWarnings("unused") RAbstractRawVector left, RAbstractContainer right) { + return right.getElementClass() == RFactor.class; + } + // implementation private void copyAttributes(RVector ret, RAbstractVector left, RAbstractVector right) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java index d8c732f9d642aef5e1f54539446aa27a8299a6a0..40bec6926fa771ed92988b51ca2b2782a1a1ffd0 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java @@ -22,6 +22,8 @@ */ package com.oracle.truffle.r.nodes.binary; +import java.util.*; + import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; @@ -293,12 +295,39 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { // null @Specialization - protected RLogicalVector doNull(RNull left, Object right) { + protected RLogicalVector doNull(RNull left, RNull right) { return RDataFactory.createLogicalVector(0); } - @Specialization - protected RLogicalVector doNull(Object left, RNull right) { + @Specialization(guards = "!isFactor") + protected RLogicalVector doNull(RNull left, RAbstractContainer right) { + return RDataFactory.createLogicalVector(0); + } + + @Specialization(guards = "!isFactor") + protected RLogicalVector doNull(RAbstractContainer left, RNull right) { + return RDataFactory.createLogicalVector(0); + } + + @Specialization(guards = "!meaningfulOp") + protected RLogicalVector doFactorOpError(RFactor left, RNull right) { + RError.warning(getEncapsulatingSourceSection(), RError.Message.NOT_MEANINGFUL_FOR_FACTORS, logic.opName()); + return RDataFactory.createNAVector(left.getLength() == 0 ? 1 : left.getLength()); + } + + @Specialization(guards = "!meaningfulOp") + protected RLogicalVector doFactorOpError(RNull left, RFactor right) { + RError.warning(getEncapsulatingSourceSection(), RError.Message.NOT_MEANINGFUL_FOR_FACTORS, logic.opName()); + return RDataFactory.createNAVector(right.getLength() == 0 ? 1 : right.getLength()); + } + + @Specialization(guards = "meaningfulOp") + protected RLogicalVector doFactorOp(RFactor left, RNull right) { + return RDataFactory.createLogicalVector(0); + } + + @Specialization(guards = "meaningfulOp") + protected RLogicalVector doFactorOp(RNull left, RFactor right) { return RDataFactory.createLogicalVector(0); } @@ -703,72 +732,62 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { // factor and scalar - @Specialization(guards = "!isEq") - protected RLogicalVector doFactorOp(RFactor left, Object right) { - throw RError.error(getEncapsulatingSourceSection(), RError.Message.NOT_MEANINGFUL_FOR_FACTORS, logic.opName()); - } - - @Specialization(guards = "!isEq") - protected RLogicalVector doFactorOp(Object left, RFactor right) { - throw RError.error(getEncapsulatingSourceSection(), RError.Message.NOT_MEANINGFUL_FOR_FACTORS, logic.opName()); - } - - @Specialization(guards = "isEq") + @Specialization(guards = "meaningfulOp") protected RLogicalVector doFactorOp(RFactor left, int right) { return performStringVectorOp(RClosures.createFactorToStringVector(left, leftNACheck), RRuntime.intToString(right, false), false); } - @Specialization(guards = "isEq") + @Specialization(guards = "meaningfulOp") protected RLogicalVector doFactorOp(int left, RFactor right) { return performStringVectorOp(RClosures.createFactorToStringVector(right, leftNACheck), RRuntime.intToString(left, false), true); } - @Specialization(guards = "isEq") + @Specialization(guards = "meaningfulOp") protected RLogicalVector doFactorOp(RFactor left, double right) { return performStringVectorOp(RClosures.createFactorToStringVector(left, leftNACheck), RRuntime.doubleToString(right), false); } - @Specialization(guards = "isEq") + @Specialization(guards = "meaningfulOp") protected RLogicalVector doFactorOp(double left, RFactor right) { return performStringVectorOp(RClosures.createFactorToStringVector(right, leftNACheck), RRuntime.doubleToString(left), true); } - @Specialization(guards = "isEq") + @Specialization(guards = "meaningfulOp") protected RLogicalVector doFactorOp(RFactor left, byte right) { return performStringVectorOp(RClosures.createFactorToStringVector(left, leftNACheck), RRuntime.logicalToString(right), false); } - @Specialization(guards = "isEq") + @Specialization(guards = "meaningfulOp") protected RLogicalVector doFactorOp(byte left, RFactor right) { return performStringVectorOp(RClosures.createFactorToStringVector(right, leftNACheck), RRuntime.logicalToString(left), false); } - @Specialization(guards = "isEq") + @Specialization(guards = "meaningfulOp") protected RLogicalVector doFactorOp(RFactor left, String right) { return performStringVectorOp(RClosures.createFactorToStringVector(left, leftNACheck), right, false); } - @Specialization(guards = "isEq") + @Specialization(guards = "meaningfulOp") protected RLogicalVector doFactorOp(String left, RFactor right) { return performStringVectorOp(RClosures.createFactorToStringVector(right, leftNACheck), left, true); } - @Specialization(guards = "isEq") + @Specialization(guards = "meaningfulOp") protected RLogicalVector doFactorOp(RFactor left, RComplex right) { return performStringVectorOp(RClosures.createFactorToStringVector(left, leftNACheck), RRuntime.complexToString(right), false); } - @Specialization(guards = "isEq") + @Specialization(guards = "meaningfulOp") protected RLogicalVector doFactorOp(RComplex left, RFactor right) { return performStringVectorOp(RClosures.createFactorToStringVector(right, leftNACheck), RRuntime.complexToString(left), true); } - @Specialization(guards = "isEq") + @Specialization(guards = "meaningfulOp") protected RLogicalVector doFactorOp(RFactor left, RRaw right) { return performStringVectorOp(RClosures.createFactorToStringVector(left, leftNACheck), RRuntime.rawToString(right), false); } - @Specialization(guards = "isEq") + @Specialization(guards = "meaningfulOp") protected RLogicalVector doFactorOp(RRaw left, RFactor right) { return performStringVectorOp(RClosures.createFactorToStringVector(right, leftNACheck), RRuntime.rawToString(left), true); } @@ -863,22 +882,22 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { return performStringVectorOpSameLength(left, RClosures.createIntToStringVector(right, rightNACheck)); } - @Specialization(guards = {"!areSameLength", "isEq"}) + @Specialization(guards = {"!areSameLength", "meaningfulOp"}) protected RLogicalVector doIntVectorDifferentLength(RAbstractIntVector left, RFactor right) { return performStringVectorOpDifferentLength(RClosures.createIntToStringVector(left, leftNACheck), RClosures.createFactorToStringVector(right, leftNACheck)); } - @Specialization(guards = {"areSameLength", "isEq"}) + @Specialization(guards = {"areSameLength", "meaningfulOp"}) protected RLogicalVector doIntVectorSameLength(RAbstractIntVector left, RFactor right) { return performStringVectorOpSameLength(RClosures.createIntToStringVector(left, leftNACheck), RClosures.createFactorToStringVector(right, leftNACheck)); } - @Specialization(guards = {"!areSameLength", "isEq"}) + @Specialization(guards = {"!areSameLength", "meaningfulOp"}) protected RLogicalVector doIntVectorDifferentLength(RFactor left, RAbstractIntVector right) { return performStringVectorOpDifferentLength(RClosures.createFactorToStringVector(left, leftNACheck), RClosures.createIntToStringVector(right, rightNACheck)); } - @Specialization(guards = {"areSameLength", "isEq"}) + @Specialization(guards = {"areSameLength", "meaningfulOp"}) protected RLogicalVector doIntVectorSameLength(RFactor left, RAbstractIntVector right) { return performStringVectorOpSameLength(RClosures.createFactorToStringVector(left, leftNACheck), RClosures.createIntToStringVector(right, rightNACheck)); } @@ -975,22 +994,22 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { return performStringVectorOpSameLength(left, RClosures.createDoubleToStringVector(right, rightNACheck)); } - @Specialization(guards = {"!areSameLength", "isEq"}) + @Specialization(guards = {"!areSameLength", "meaningfulOp"}) protected RLogicalVector doDoubleVectorDifferentLength(RAbstractDoubleVector left, RFactor right) { return performStringVectorOpDifferentLength(RClosures.createDoubleToStringVector(left, leftNACheck), RClosures.createFactorToStringVector(right, leftNACheck)); } - @Specialization(guards = {"areSameLength", "isEq"}) + @Specialization(guards = {"areSameLength", "meaningfulOp"}) protected RLogicalVector doDoubleVectorSameLength(RAbstractDoubleVector left, RFactor right) { return performStringVectorOpSameLength(RClosures.createDoubleToStringVector(left, leftNACheck), RClosures.createFactorToStringVector(right, leftNACheck)); } - @Specialization(guards = {"!areSameLength", "isEq"}) + @Specialization(guards = {"!areSameLength", "meaningfulOp"}) protected RLogicalVector doDoubleVectorDifferentLength(RFactor left, RAbstractDoubleVector right) { return performStringVectorOpDifferentLength(RClosures.createFactorToStringVector(left, leftNACheck), RClosures.createDoubleToStringVector(right, rightNACheck)); } - @Specialization(guards = {"areSameLength", "isEq"}) + @Specialization(guards = {"areSameLength", "meaningfulOp"}) protected RLogicalVector doDoubleVectorSameLength(RFactor left, RAbstractDoubleVector right) { return performStringVectorOpSameLength(RClosures.createFactorToStringVector(left, leftNACheck), RClosures.createDoubleToStringVector(right, rightNACheck)); } @@ -1067,22 +1086,22 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { return performStringVectorOpSameLength(left, RClosures.createLogicalToStringVector(right, rightNACheck)); } - @Specialization(guards = {"!areSameLength", "isEq"}) + @Specialization(guards = {"!areSameLength", "meaningfulOp"}) protected RLogicalVector doLogicalVectorDifferentLength(RAbstractLogicalVector left, RFactor right) { return performStringVectorOpDifferentLength(RClosures.createLogicalToStringVector(left, leftNACheck), RClosures.createFactorToStringVector(right, leftNACheck)); } - @Specialization(guards = {"areSameLength", "isEq"}) + @Specialization(guards = {"areSameLength", "meaningfulOp"}) protected RLogicalVector doLogicalVectorSameLength(RAbstractLogicalVector left, RFactor right) { return performStringVectorOpSameLength(RClosures.createLogicalToStringVector(left, leftNACheck), RClosures.createFactorToStringVector(right, leftNACheck)); } - @Specialization(guards = {"!areSameLength", "isEq"}) + @Specialization(guards = {"!areSameLength", "meaningfulOp"}) protected RLogicalVector doLogicalVectorDifferentLength(RFactor left, RAbstractLogicalVector right) { return performStringVectorOpDifferentLength(RClosures.createFactorToStringVector(left, leftNACheck), RClosures.createLogicalToStringVector(right, rightNACheck)); } - @Specialization(guards = {"areSameLength", "isEq"}) + @Specialization(guards = {"areSameLength", "meaningfulOp"}) protected RLogicalVector doLogicalVectorSameLength(RFactor left, RAbstractLogicalVector right) { return performStringVectorOpSameLength(RClosures.createFactorToStringVector(left, leftNACheck), RClosures.createLogicalToStringVector(right, rightNACheck)); } @@ -1139,22 +1158,22 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { return performStringVectorOpSameLength(left, right); } - @Specialization(guards = {"!areSameLength", "isEq"}) + @Specialization(guards = {"!areSameLength", "meaningfulOp"}) protected RLogicalVector doStringVectorDifferentLength(RStringVector left, RFactor right) { return performStringVectorOpDifferentLength(left, RClosures.createFactorToStringVector(right, rightNACheck)); } - @Specialization(guards = {"areSameLength", "isEq"}) + @Specialization(guards = {"areSameLength", "meaningfulOp"}) protected RLogicalVector doStringVectorSameLength(RStringVector left, RFactor right) { return performStringVectorOpSameLength(left, RClosures.createFactorToStringVector(right, rightNACheck)); } - @Specialization(guards = {"!areSameLength", "isEq"}) + @Specialization(guards = {"!areSameLength", "meaningfulOp"}) protected RLogicalVector doStringVectorDifferentLength(RFactor left, RStringVector right) { return performStringVectorOpDifferentLength(RClosures.createFactorToStringVector(left, rightNACheck), right); } - @Specialization(guards = {"areSameLength", "isEq"}) + @Specialization(guards = {"areSameLength", "meaningfulOp"}) protected RLogicalVector doStringVectorSameLength(RFactor left, RStringVector right) { return performStringVectorOpSameLength(RClosures.createFactorToStringVector(left, rightNACheck), right); } @@ -1201,56 +1220,68 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { // factor and vectors - @Specialization(guards = {"!areSameLength", "isEq"}) + @Specialization(guards = {"!areSameLength", "meaningfulOp"}) protected RLogicalVector doStringVectorDifferentLength(RFactor left, RFactor right) { return performStringVectorOpDifferentLength(RClosures.createFactorToStringVector(left, rightNACheck), RClosures.createFactorToStringVector(right, rightNACheck)); } - @Specialization(guards = {"areSameLength", "isEq"}) + @Specialization(guards = {"areSameLength", "meaningfulOp"}) protected RLogicalVector doStringVectorSameLength(RFactor left, RFactor right) { return performStringVectorOpSameLength(RClosures.createFactorToStringVector(left, rightNACheck), RClosures.createFactorToStringVector(right, rightNACheck)); } - @Specialization(guards = {"!areSameLength", "isEq"}) + @Specialization(guards = {"!areSameLength", "meaningfulOp"}) protected RLogicalVector doStringVectorDifferentLength(RFactor left, RAbstractComplexVector right) { return performStringVectorOpDifferentLength(RClosures.createFactorToStringVector(left, rightNACheck), RClosures.createComplexToStringVector(right, rightNACheck)); } - @Specialization(guards = {"areSameLength", "isEq"}) + @Specialization(guards = {"areSameLength", "meaningfulOp"}) protected RLogicalVector doStringVectorSameLength(RFactor left, RAbstractComplexVector right) { return performStringVectorOpSameLength(RClosures.createFactorToStringVector(left, rightNACheck), RClosures.createComplexToStringVector(right, rightNACheck)); } - @Specialization(guards = {"!areSameLength", "isEq"}) + @Specialization(guards = {"!areSameLength", "meaningfulOp"}) protected RLogicalVector doStringVectorDifferentLength(RAbstractComplexVector left, RFactor right) { return performStringVectorOpDifferentLength(RClosures.createComplexToStringVector(left, leftNACheck), RClosures.createFactorToStringVector(right, rightNACheck)); } - @Specialization(guards = {"areSameLength", "isEq"}) + @Specialization(guards = {"areSameLength", "meaningfulOp"}) protected RLogicalVector doStringVectorSameLength(RAbstractComplexVector left, RFactor right) { return performStringVectorOpSameLength(RClosures.createComplexToStringVector(left, leftNACheck), RClosures.createFactorToStringVector(right, rightNACheck)); } - @Specialization(guards = {"!areSameLength", "isEq"}) + @Specialization(guards = {"!areSameLength", "meaningfulOp"}) protected RLogicalVector doStringVectorDifferentLength(RFactor left, RRawVector right) { return performStringVectorOpDifferentLength(RClosures.createFactorToStringVector(left, rightNACheck), RClosures.createRawToStringVector(right, rightNACheck)); } - @Specialization(guards = {"areSameLength", "isEq"}) + @Specialization(guards = {"areSameLength", "meaningfulOp"}) protected RLogicalVector doStringVectorSameLength(RFactor left, RRawVector right) { return performStringVectorOpSameLength(RClosures.createFactorToStringVector(left, rightNACheck), RClosures.createRawToStringVector(right, rightNACheck)); } - @Specialization(guards = {"!areSameLength", "isEq"}) + @Specialization(guards = {"!areSameLength", "meaningfulOp"}) protected RLogicalVector doStringVectorDifferentLengthRRawVector(RRawVector left, RFactor right) { return performStringVectorOpDifferentLength(RClosures.createRawToStringVector(left, leftNACheck), RClosures.createFactorToStringVector(right, rightNACheck)); } - @Specialization(guards = {"areSameLength", "isEq"}) + @Specialization(guards = {"areSameLength", "meaningfulOp"}) protected RLogicalVector doStringVectorSameLengthRRawVector(RRawVector left, RFactor right) { return performStringVectorOpSameLength(RClosures.createRawToStringVector(left, leftNACheck), RClosures.createFactorToStringVector(right, rightNACheck)); } + @Specialization(guards = "!meaningfulOp") + protected RLogicalVector doFactorOp(RFactor left, RAbstractContainer right) { + RError.warning(getEncapsulatingSourceSection(), RError.Message.NOT_MEANINGFUL_FOR_FACTORS, logic.opName()); + return RDataFactory.createNAVector(Math.max(left.getLength(), right.getLength())); + } + + @Specialization(guards = "!meaningfulOp") + protected RLogicalVector doFactorOp(RAbstractContainer left, RFactor right) { + RError.warning(getEncapsulatingSourceSection(), RError.Message.NOT_MEANINGFUL_FOR_FACTORS, logic.opName()); + return RDataFactory.createNAVector(Math.max(left.getLength(), right.getLength())); + } + // complex vector and vectors @Specialization(guards = "!areSameLength") @@ -1338,16 +1369,48 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { // guards - public boolean isEq(RFactor left, RFactor right) { - return logic instanceof BinaryCompare.Equal || logic instanceof BinaryCompare.NotEqual; + public boolean isFactor(RAbstractContainer left, RNull right) { + return left.getElementClass() == RFactor.class; + } + + public boolean isFactor(RNull left, RAbstractContainer right) { + return right.getElementClass() == RFactor.class; + } + + public boolean isFactor(RFactor left, RAbstractContainer right) { + return right.getElementClass() == RFactor.class; + } + + public boolean isFactor(RAbstractContainer left, RFactor right) { + return left.getElementClass() == RFactor.class; + } + + public boolean meaningfulOp(RFactor left, RFactor right) { + return logic instanceof BinaryCompare.Equal || logic instanceof BinaryCompare.NotEqual || (left.isOrdered() && right.isOrdered()); + } + + public boolean meaningfulOp(RFactor left, RNull right) { + return logic instanceof BinaryCompare.Equal || logic instanceof BinaryCompare.NotEqual || left.isOrdered(); + } + + public boolean meaningfulOp(RNull left, RFactor right) { + return logic instanceof BinaryCompare.Equal || logic instanceof BinaryCompare.NotEqual || right.isOrdered(); + } + + public boolean meaningfulOp(RFactor left, RAbstractContainer right) { + return logic instanceof BinaryCompare.Equal || logic instanceof BinaryCompare.NotEqual || left.isOrdered(); + } + + public boolean meaningfulOp(RAbstractContainer left, RFactor right) { + return logic instanceof BinaryCompare.Equal || logic instanceof BinaryCompare.NotEqual || right.isOrdered(); } - public boolean isEq(RFactor left, Object right) { - return logic instanceof BinaryCompare.Equal || logic instanceof BinaryCompare.NotEqual; + public boolean meaningfulOp(RFactor left, Object right) { + return logic instanceof BinaryCompare.Equal || logic instanceof BinaryCompare.NotEqual || left.isOrdered(); } - public boolean isEq(Object left, RFactor right) { - return !(logic instanceof BinaryCompare.Equal || logic instanceof BinaryCompare.NotEqual); + public boolean meaningfulOp(Object left, RFactor right) { + return logic instanceof BinaryCompare.Equal || logic instanceof BinaryCompare.NotEqual || right.isOrdered(); } private boolean isVectorizedLogicalOp() { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java index facf67fe88f69062a1065ea7b445b25642c32762..20559f41ade8dd2f40dbcd1b560c14edfe926d29 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java @@ -31,6 +31,8 @@ public abstract class CastTypeNode extends BinaryNode { @Child private CastToVectorNode castToVectorNode; @Child private TypeofNode typeof; + @Child private CastTypeNode castRecursive; + public abstract Object execute(VirtualFrame frame, Object value, RType type); @SuppressWarnings("unused") @@ -94,6 +96,12 @@ public abstract class CastTypeNode extends BinaryNode { return null; } + @Specialization + protected Object doCastDataFrame(VirtualFrame frame, RDataFrame value, RType type) { + initCastRecursive(); + return castRecursive.execute(frame, value.getVector(), type); + } + @SuppressWarnings("unused") protected static boolean isString(RAbstractVector value, RType type) { return type == RType.Character; @@ -190,4 +198,12 @@ public abstract class CastTypeNode extends BinaryNode { castListNode = insert(CastListNodeFactory.create(null, false, false, false)); } } + + private void initCastRecursive() { + if (castRecursive == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + castRecursive = insert(CastTypeNodeFactory.create(null, null)); + } + } + } 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 85da4d65572fe1f9bc1bb4d86e7b07829df31916..4bb6e4b09dad0323ae6beefbe746292b09d66978 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.nodes/src/com/oracle/truffle/r/nodes/function/DispatchedCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/DispatchedCallNode.java index 0607daa5d946784ed1aa1c723dfb0fbd9acc57ee..c3df06bafcf2058493a3bbc81fffd886cabef197 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/DispatchedCallNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/DispatchedCallNode.java @@ -13,6 +13,7 @@ package com.oracle.truffle.r.nodes.function; import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; import com.oracle.truffle.r.nodes.*; import com.oracle.truffle.r.runtime.*; @@ -49,6 +50,7 @@ public abstract class DispatchedCallNode extends RNode { public abstract Object executeInternal(VirtualFrame frame, RStringVector type, Object[] args); + @NodeInfo(cost = NodeCost.UNINITIALIZED) private static final class UninitializedDispatchedCallNode extends DispatchedCallNode { private final int depth; private final String genericName; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetMissingValueNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetMissingValueNode.java index 276d56ed99d80120a4f0da05b06458cfc92800fd..a4f59b9f05ded0ab468a822ece4460f20445d512 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetMissingValueNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetMissingValueNode.java @@ -24,19 +24,22 @@ package com.oracle.truffle.r.nodes.function; import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.r.nodes.*; +import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.r.nodes.access.*; /** * This is a node abstraction for the functionality defined in * {@link RMissingHelper#getMissingValue(Frame,Symbol)}. */ -public abstract class GetMissingValueNode extends RNode { +public abstract class GetMissingValueNode extends Node { public static GetMissingValueNode create(Symbol sym) { return new UninitializedGetMissingValueNode(sym); } + public abstract Object execute(Frame frame); + + @NodeInfo(cost = NodeCost.UNINITIALIZED) private static final class UninitializedGetMissingValueNode extends GetMissingValueNode { private final Symbol sym; @@ -46,11 +49,10 @@ public abstract class GetMissingValueNode extends RNode { } @Override - public Object execute(VirtualFrame frame) { + public Object execute(Frame frame) { CompilerDirectives.transferToInterpreterAndInvalidate(); FrameSlot slot = frame.getFrameDescriptor().findFrameSlot(sym.getName()); - GetMissingValueNode gmvn = new ResolvedGetMissingValueNode(slot); - return replace(gmvn).execute(frame); + return replace(new ResolvedGetMissingValueNode(slot)).execute(frame); } } @@ -64,7 +66,7 @@ public abstract class GetMissingValueNode extends RNode { } @Override - public Object execute(VirtualFrame frame) { + public Object execute(Frame frame) { if (slot == null) { return null; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java index 766b15a752c1a731dc85e24abf2aee9e48bf6d28..b108aa97e1a4b0408ac871b8da0b761373374038 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java @@ -74,13 +74,13 @@ import com.oracle.truffle.r.runtime.data.*; * U = {@link UninitializedCallNode}: Forms the uninitialized end of the function PIC * D = {@link DispatchedCallNode}: Function fixed, no varargs * G = {@link GenericCallNode}: Function arbitrary, no varargs (generic case) - * + * * UV = {@link UninitializedCallNode} with varargs, * UVC = {@link UninitializedVarArgsCacheCallNode} with varargs, for varargs cache * DV = {@link DispatchedVarArgsCallNode}: Function fixed, with cached varargs * DGV = {@link DispatchedGenericVarArgsCallNode}: Function fixed, with arbitrary varargs (generic case) * GV = {@link GenericVarArgsCallNode}: Function arbitrary, with arbitrary varargs (generic case) - * + * * (RB = {@link RBuiltinNode}: individual functions that are builtins are represented by this node * which is not aware of caching). Due to {@link CachedCallNode} (see below) this is transparent to * the cache and just behaves like a D/DGV) @@ -93,11 +93,11 @@ import com.oracle.truffle.r.runtime.data.*; * non varargs, max depth: * | * D-D-D-U - * + * * no varargs, generic (if max depth is exceeded): * | * D-D-D-D-G - * + * * varargs: * | * DV-DV-UV <- function call target identity level cache @@ -105,7 +105,7 @@ import com.oracle.truffle.r.runtime.data.*; * DV * | * UVC <- varargs signature level cache - * + * * varargs, max varargs depth exceeded: * | * DV-DV-UV @@ -117,7 +117,7 @@ import com.oracle.truffle.r.runtime.data.*; * DV * | * DGV - * + * * varargs, max function depth exceeded: * | * DV-DV-DV-DV-GV @@ -374,6 +374,7 @@ public abstract class RCallNode extends RNode { * * @see RCallNode */ + @NodeInfo(cost = NodeCost.UNINITIALIZED) public static final class UninitializedCallNode extends RootCallNode { private final int depth; @@ -544,6 +545,7 @@ public abstract class RCallNode extends RNode { * * @see RCallNode */ + @NodeInfo(cost = NodeCost.UNINITIALIZED) public static final class UninitializedVarArgsCacheCallNode extends VarArgsCacheCallNode { @Child private CallArgumentsNode args; private int depth = 1; // varargs cached is started with a [DV] DispatchedVarArgsCallNode diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java index 655fee04826b8ac6a488464abe2a5b5f652e20ea..84d79f708cc8fa6f78c32fde97ae370ebd6833e7 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java @@ -34,30 +34,6 @@ import com.oracle.truffle.r.runtime.data.RPromise.*; * would induce unnecessary dependencies otherwise. */ public class RMissingHelper { - /** - * This function determines whether an arguments value - given as 'value' - is missing. An - * argument is missing when it has not been provided to the current function call (DEFAULTED or - * {@code value == RMissing.instance}, if argument has default value), OR if the value that has - * been provided once was a missing argument. (cp. R language definition and Internals 1.5.1 - * Missingness). - * - * @param value The value that should be examined - * @return <code>true</code> iff this value is 'missing' in the definition of R - */ - public static boolean isMissing(Object value, PromiseProfile promiseProfile) { - if (value == RMissing.instance) { - return true; - } - - // This might be a promise... - if (value instanceof RPromise) { - RPromise promise = (RPromise) value; - if (promise.isDefault(promiseProfile) || isMissingSymbol(promise)) { - return true; - } - } - return false; - } /** * This method determines whether a given {@link Symbol} is missing in the given frame. This is diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java index 0a6857b8a718338e1c25ff723bde49040e66f110..10268ef185d1ae4d183080c91af702c3b47cf6a7 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java @@ -22,6 +22,8 @@ */ package com.oracle.truffle.r.nodes.unary; +import java.util.*; + import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.*; @@ -179,6 +181,18 @@ public abstract class CastLogicalNode extends CastNode { return missing; } + @Specialization + protected Object asLogical(VirtualFrame frame, RDataFrame dataFrame) { + return castLogicalRecursive(frame, dataFrame.getVector()); + } + + @Specialization + protected RLogicalVector asLogical(RFactor factor) { + byte[] data = new byte[factor.getLength()]; + Arrays.fill(data, RRuntime.LOGICAL_NA); + return RDataFactory.createLogicalVector(data, RDataFactory.INCOMPLETE_VECTOR); + } + @Fallback @TruffleBoundary public int doOther(Object operand) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RConnection.java index 760444abf70eb99ff0857f3f95f4984de75518e5..5ca7160374ec866c2568f03c256f56a51631f99b 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RConnection.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RConnection.java @@ -123,10 +123,17 @@ public abstract class RConnection implements RClassHierarchy { } /** - * Return the underlying input stream (for internal use). + * Return the underlying input stream (for internal use). TODO Replace with a more principled + * solution. */ public abstract InputStream getInputStream() throws IOException; + /** + * Return the underlying output stream (for internal use). TODO Replace with a more principled + * solution. + */ + public abstract OutputStream getOutputStream() throws IOException; + /** * Close the connection. */ diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java index 81d268d5a291760d87055e89ec544852b701e580..f68e681012a1566a26c49a05059bac7370b4b49e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java @@ -559,7 +559,8 @@ public final class RError extends RuntimeException { IS_NA_TO_NON_VECTOR("is.na() applied to non-(list or vector) of type '%s'"), NOT_MEANINGFUL_FOR_FACTORS("%s not meaningful for factors"), INPUTS_DIFFERENT_LENGTHS("inputs of different lengths"), - MATRIX_LIKE_REQUIRED("a matrix-like object is required as argument to '%s'"); + MATRIX_LIKE_REQUIRED("a matrix-like object is required as argument to '%s'"), + NOT_MEANINGFUL_FOR_ORDERED_FACTORS("'%s' is not meaningful for ordered factors"); public final String message; private final boolean hasArgs; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java index 69f26f12cc788fbc6fa1b76439f0831912e81247..38bebb8777999c0fcb84ac1162a8fb7898d9008b 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java @@ -100,6 +100,8 @@ public class RRuntime { public static final String[] CLASS_INTEGER = new String[]{"integer", "numeric"}; public static final String[] CLASS_DOUBLE = new String[]{"double", "numeric"}; + public static final String CLASS_ORDERED = "ordered"; + public static final String WHICH = "which"; public static final String WHAT = "what"; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java index 290652e0f5d82a2b221b04331195ec03646c1439..e2f49ac88dcbb020b042f773dd469427bde058a0 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java @@ -362,7 +362,7 @@ public class RSerialize { } else if (tag.equals(RRuntime.ROWNAMES_ATTR_KEY)) { vec.setRowNames(car); } else if (tag.equals(RRuntime.CLASS_ATTR_KEY)) { - RVector.setClassAttr(vec, (RStringVector) car, null, null); + result = RVector.setVectorClassAttr(vec, (RStringVector) car, null, null); } else { vec.setAttr(tag, car); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java index 2746fdb5eac3fb98dfe9dfb6e213a7fddb7f1a2c..4b795f9d393c001b004791d4978f971340937459 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.runtime.data; +import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.env.*; /** @@ -46,7 +47,7 @@ public interface RAttributable { /** * Set the attribute {@code name} to {@code value}, overwriting any existing value. This is - * generic; a class may need to override this to handle certain attributes specially, + * generic; a class may need to override this to handle certain attributes specially. */ default void setAttr(String name, Object value) { RAttributes attributes = getAttributes(); @@ -58,7 +59,7 @@ public interface RAttributable { /** * Remove the attribute {@code name}. No error if {@code name} is not an attribute. This is - * generic; a class may need to override this to handle certain attributes specially, + * generic; a class may need to override this to handle certain attributes specially. */ default void removeAttr(String name) { RAttributes attributes = getAttributes(); @@ -66,4 +67,10 @@ public interface RAttributable { attributes.remove(name); } } + + default RAttributable setClassAttr(RStringVector classAttr) { + setAttr(RRuntime.CLASS_ATTR_KEY, classAttr); + return this; + } + } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java index d7ae5ec067ca56b881ee81d3ea2f997a20ae5a35..8c8f02ad26173dd8b5ff47c9e03392259e47dafc 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java @@ -22,6 +22,8 @@ */ package com.oracle.truffle.r.runtime.data; +import java.util.*; + import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.RPromise.Closure; @@ -176,6 +178,12 @@ public final class RDataFactory { return traceDataCreated(new RLogicalVector(data, complete, dims, names)); } + public static RLogicalVector createNAVector(int length) { + byte[] data = new byte[length]; + Arrays.fill(data, RRuntime.LOGICAL_NA); + return createLogicalVector(data, INCOMPLETE_VECTOR); + } + public static RIntSequence createAscendingRange(int start, int end) { assert start <= end; return traceDataCreated(new RIntSequence(start, 1, end - start + 1)); @@ -304,8 +312,8 @@ public final class RDataFactory { return traceDataCreated(new RExpression(list)); } - public static RFactor createFactor(RIntVector vector) { - return traceDataCreated(new RFactor(vector)); + public static RFactor createFactor(RIntVector vector, boolean ordered) { + return traceDataCreated(new RFactor(vector, ordered)); } public static RVector createObjectVector(Object[] data, boolean completeVector) { 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 d008396f97af91560eecd38010df53bcf614e6a7..41d6acbfbe38c1d2413e27f4028c8e0964754098 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(); @@ -137,4 +142,9 @@ public final class RDataFrame implements RShareable, RAbstractContainer { return vector.getElementIndexByNameInexact(name); } + @Override + public RAbstractContainer setClassAttr(RStringVector classAttr) { + return RVector.setVectorClassAttr(vector, classAttr, this, null); + } + } 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 c4ee0a45e9aca3001bf58459af2b17f15d7044e7..0d3e58755205d0179cc655741041b146bf8fc826 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 f58a701846c0a9f8696b6db0f1712476222caf6e..95330a9bb1f29368496be5893f746564e9f94bec 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 @@ -28,14 +28,21 @@ public final class RFactor implements RShareable, RAbstractContainer { private RIntVector vector; - public RFactor(RIntVector vector) { + private final boolean ordered; + + public RFactor(RIntVector vector, boolean ordered) { this.vector = vector; + this.ordered = ordered; } public RIntVector getVector() { return vector; } + public boolean isOrdered() { + return ordered; + } + @Override public int getLength() { return vector.getLength(); @@ -63,7 +70,7 @@ public final class RFactor implements RShareable, RAbstractContainer { @Override public RFactor copy() { - return RDataFactory.createFactor((RIntVector) vector.copy()); + return RDataFactory.createFactor((RIntVector) vector.copy(), ordered); } @Override @@ -71,6 +78,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(); @@ -141,4 +153,9 @@ public final class RFactor implements RShareable, RAbstractContainer { vector.setLevels(newLevels); } + @Override + public RAbstractContainer setClassAttr(RStringVector classAttr) { + return RVector.setVectorClassAttr(vector, classAttr, null, this); + } + } 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 b664d05590357305d8e9a9d024c0049e8f2c2b1b..6bf246f615e87d578df04b0b48e587602094c903 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 6e5ac36178c796ac3ebbe05c84166da108627325..add5a33aafe4df22f7aaed9308fd343d29890df1 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 f4a3e81da5c94fa07805b1fa1f5d3920c82baa19..50e8e7f91f8bbd6391aafc4ffa6a4c805809ccc2 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 @@ -180,7 +180,7 @@ public abstract class RVector extends RBounded implements RShareable, RAbstractV } else if (name.equals(RRuntime.ROWNAMES_ATTR_KEY)) { setRowNames(value); } else if (name.equals(RRuntime.CLASS_ATTR_KEY)) { - setClassAttr(this, (RStringVector) value, null, null); + throw Utils.nyi("The \"class\" attribute should be set using a separate method"); } else { attributes.put(name, value); } @@ -204,7 +204,7 @@ public abstract class RVector extends RBounded implements RShareable, RAbstractV } else if (name.equals(RRuntime.ROWNAMES_ATTR_KEY)) { setRowNames(null); } else if (name.equals(RRuntime.CLASS_ATTR_KEY)) { - setClassAttr(this, (RStringVector) null, null, null); + throw Utils.nyi("The \"class\" attribute should be reset using a separate method"); } else { attributes.remove(name); } @@ -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) { @@ -400,17 +396,33 @@ public abstract class RVector extends RBounded implements RShareable, RAbstractV } } - public static RAbstractContainer setClassAttr(RVector vector, RStringVector classAttr, RAbstractContainer enclosingDataFrame, RAbstractContainer enclosingFactor) { + @Override + public RAbstractContainer setClassAttr(RStringVector classAttr) { + return setClassAttrInternal(this, classAttr, null, null, true); + } + + public static RAbstractContainer setVectorClassAttr(RVector vector, RStringVector classAttr, RAbstractContainer enclosingDataFrame, RAbstractContainer enclosingFactor) { + return setClassAttrInternal(vector, classAttr, enclosingDataFrame, enclosingFactor, false); + } + + private static RAbstractContainer setClassAttrInternal(RVector vector, RStringVector classAttr, RAbstractContainer enclosingDataFrame, RAbstractContainer enclosingFactor, boolean convertToInt) { if (vector.attributes == null && classAttr != null && classAttr.getLength() != 0) { vector.initAttributes(); } if (vector.attributes != null && (classAttr == null || classAttr.getLength() == 0)) { vector.removeAttributeMapping(RRuntime.CLASS_ATTR_KEY); - // class attribute removed - no longer a data frame (even if it was before) + // class attribute removed - no longer a data frame or factor (even if it was before) return vector; } else if (classAttr != null && classAttr.getLength() != 0) { + boolean ordered = false; for (int i = 0; i < classAttr.getLength(); i++) { - if (RType.DataFrame.getName().equals(classAttr.getDataAt(i))) { + String attr = classAttr.getDataAt(i); + if (RRuntime.CLASS_ORDERED.equals(attr)) { + // "ordered" must be specified before "factor" - hence it's enough to do the + // check only before encountering the "factor" + ordered = true; + } + if (RType.DataFrame.getName().equals(attr)) { vector.putAttribute(RRuntime.CLASS_ATTR_KEY, classAttr); if (enclosingDataFrame != null) { // was a frame and still is a frame @@ -419,18 +431,31 @@ public abstract class RVector extends RBounded implements RShareable, RAbstractV // it's a data frame now return RDataFactory.createDataFrame(vector); } - } else if (RType.Factor.getName().equals(classAttr.getDataAt(i))) { - if (vector.getElementClass() != RInt.class) { - // TODO: add source section - throw RError.error(null, RError.Message.ADDING_INVALID_CLASS, "factor"); - } + } else if (RType.Factor.getName().equals(attr)) { vector.putAttribute(RRuntime.CLASS_ATTR_KEY, classAttr); if (enclosingFactor != null) { // was a factor and still is a factor return enclosingFactor; } else { + RIntVector resVector; + if (vector.getElementClass() != RInt.class) { + if (vector.getElementClass() == RDouble.class && convertToInt) { + RAbstractDoubleVector sourceVector = (RAbstractDoubleVector) vector; + int[] data = new int[sourceVector.getLength()]; + for (int j = 0; j < data.length; j++) { + data[j] = RRuntime.double2int(sourceVector.getDataAt(j)); + } + resVector = RDataFactory.createIntVector(data, sourceVector.isComplete()); + resVector.copyAttributesFrom(sourceVector); + } else { + // TODO: add source section + throw RError.error(null, RError.Message.ADDING_INVALID_CLASS, "factor"); + } + } else { + resVector = (RIntVector) vector; + } // it's a factor now - return RDataFactory.createFactor((RIntVector) vector); + return RDataFactory.createFactor(resVector, ordered); } } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToStringVectorClosure.java index cb2c3ca812dd0859281f3f864c63d0e840635b0a..e437f164d4b32c3244ebaf65e0ed62e676d3ae35 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToStringVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToStringVectorClosure.java @@ -42,13 +42,24 @@ public class RFactorToStringVectorClosure extends RToStringVectorClosure impleme if (this.levels == null) { RError.warning(RError.Message.IS_NA_TO_NON_VECTOR, "NULL"); } + naCheck.enable(this.vector); } public String getDataAt(int index) { - if (levels == null) { + if (levels == null || levels.getLength() == 0) { return RRuntime.STRING_NA; } else { - return this.levels.getDataAt(vector.getDataAt(index) - 1); + int val = vector.getDataAt(index); + if (naCheck.check(val)) { + return RRuntime.STRING_NA; + } else { + String l = levels.getDataAt(val - 1); + if (naCheck.check(l)) { + return "NA"; // for comparison + } else { + return l; + } + } } } } 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 73dfc6e291dca2e4d5c4fd4d1128f050665789cb..8c304539330942f4470444bedf2281de9eb654b4 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.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java index 1f7a32abe1f2513ef3e05c616dc5e8c7d9425a7e..bc37448c2807ca0676a435d9682e58efc4baffbd 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java @@ -136,6 +136,8 @@ public abstract class BinaryArithmetic extends Operation { return supportsIntResult; } + public abstract String opName(); + public abstract int op(int left, int right); public abstract double op(double left, double right); @@ -178,6 +180,11 @@ public abstract class BinaryArithmetic extends Operation { super(true, true, true); } + @Override + public String opName() { + return "+"; + } + @Override public int op(int left, int right) { try { @@ -227,6 +234,11 @@ public abstract class BinaryArithmetic extends Operation { super(false, false, true); } + @Override + public String opName() { + return "-"; + } + @Override public int op(int left, int right) { try { @@ -275,6 +287,11 @@ public abstract class BinaryArithmetic extends Operation { super(true, true, true); } + @Override + public String opName() { + return "*"; + } + @Override public int op(int left, int right) { try { @@ -398,6 +415,11 @@ public abstract class BinaryArithmetic extends Operation { super(false, false, false); } + @Override + public String opName() { + return "/"; + } + @Override public final int op(int left, int right) { throw RInternalError.shouldNotReachHere(); @@ -470,6 +492,11 @@ public abstract class BinaryArithmetic extends Operation { super(false, false, true); } + @Override + public String opName() { + return "%/%"; + } + @Override public int op(int left, int right) { if (right != 0) { @@ -510,6 +537,11 @@ public abstract class BinaryArithmetic extends Operation { super(false, false, true); } + @Override + public String opName() { + return "%%"; + } + @Override public int op(int left, int right) { // LICENSE: transcribed code from GNU R, which is licensed under GPL @@ -552,6 +584,11 @@ public abstract class BinaryArithmetic extends Operation { super(false, false, false); } + @Override + public String opName() { + return "^"; + } + @Override public int op(int left, int right) { throw RInternalError.shouldNotReachHere(); @@ -951,6 +988,11 @@ public abstract class BinaryArithmetic extends Operation { super(true, true, true); } + @Override + public String opName() { + throw Utils.nyi(); + } + @Override public int op(int left, int right) { return Math.max(left, right); @@ -980,6 +1022,11 @@ public abstract class BinaryArithmetic extends Operation { super(true, true, true); } + @Override + public String opName() { + throw Utils.nyi(); + } + @Override public int op(int left, int right) { return Math.min(left, right); 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 7768931c5e2f2fa0464e9e404d1d71540c1663ed..7e79b7ee32e59954bd88e49ce5d201c40ccdfd05 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 @@ -8347,6 +8347,14 @@ x [1,] 10+0i -4+0i [2,] -2+0i 0+0i +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ as.logical(factor(c("a", "b", "a"))) } +[1] NA NA NA + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ as.logical(factor(integer())) } +logical(0) + ##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor #{ x<-c("1","2","3"); class(x)<-"factor"; x } Error in class(x) <- "factor" : @@ -8357,6 +8365,28 @@ Error in class(x) <- "factor" : Error in class(x) <- "factor" : adding class "factor" to an invalid object +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-c(1L, 2L, 1L); class(x)<-c("factor", "ordered"); levels(x)<-c("a", "b"); x + "a" } +[1] NA NA NA +Warning message: +In Ops.factor(x, "a") : + not meaningful for factors + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-c(1L, 2L, 1L); class(x)<-c("factor", "ordered"); levels(x)<-c("a", "b"); x > "a" } +[1] NA NA NA +Warning message: +In Ops.factor(x, "a") : > not meaningful for factors + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-c(1L, 2L, 1L); class(x)<-c("ordered", "factor"); levels(x)<-c("a", "b"); x + "a" } +[1] NA NA NA +Warning message: +In Ops.ordered(x, "a") : '+' is not meaningful for ordered factors + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-c(1L, 2L, 1L); class(x)<-c("ordered", "factor"); levels(x)<-c("a", "b"); x > "a" } +[1] FALSE TRUE FALSE + ##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor #{ x<-c(1L,2L,3L); class(x)<-"factor"; x } Error in print.factor(1:3) : replacement has length zero @@ -8369,6 +8399,22 @@ NULL #{ x<-factor(c("a", "b", "a")); attr(x, "levels")<-character(); as.character(x) } [1] NA NA NA +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-factor(c("a", "b", "a")); is.atomic(x) } +[1] TRUE + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-factor(c("a", "b", "a")); x + "a" } +[1] NA NA NA +Warning message: +In Ops.factor(x, "a") : + not meaningful for factors + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-factor(c("a", "b", "a")); x + c("a", "b") } +[1] NA NA NA +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 == "a" } [1] TRUE FALSE TRUE @@ -8394,6 +8440,50 @@ 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"), ordered=TRUE); is.atomic(x) } +[1] TRUE + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-factor(c("a", "b", "a"), ordered=TRUE); x + "a" } +[1] NA NA NA +Warning message: +In Ops.ordered(x, "a") : '+' is not meaningful for ordered factors + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-factor(c("a", "b", "a"), ordered=TRUE); x > "a" } +[1] FALSE TRUE FALSE + ##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor #{ x<-factor(c("a", "b", "a", "c")); x == c("a", "b") } [1] TRUE TRUE TRUE FALSE @@ -8405,6 +8495,10 @@ Warning message: In y[1] <- x : number of items to replace is not a multiple of replacement length +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-factor(c("c", "b", "a", "c")); y<-c(1); y[[1]]<-x; y } +Error in y[[1]] <- x : more elements supplied than there are to replace + ##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor #{ x<-factor(c("c", "b", "a", "c")); y<-list(1); y[1]<-x; y } [[1]] @@ -8414,6 +8508,52 @@ Warning message: In y[1] <- x : number of items to replace is not a multiple of replacement length +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-factor(c("c", "b", "a", "c")); y<-list(1); y[[1]]<-x; y } +[[1]] +[1] c b a c +Levels: a b c + + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-structure(c(1,2,1), .Label=c("a", "b"), class = c('factor'), .Names=c("111","112","113")); y<-structure(c(1,2,1), .Label=c("a", "b"), class = c('factor'), .Names=c("111","112","113")); x+y } +[1] NA NA NA +Warning message: +In Ops.factor(x, y) : + not meaningful for factors + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-structure(c(1,2,1), .Label=c("a", "b"), class = c('factor'), .Names=c("111","112","113")); y<-structure(c(1,2,1), .Label=c("a", "b"), class = c('factor'), .Names=c("111","112","113")); x==y } +[1] TRUE TRUE TRUE + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-structure(c(1.1,2.2,1.1), .Label=c("a", "b"), class = c('factor')); attributes(x) } +$levels +[1] "a" "b" + +$class +[1] "factor" + + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-structure(c(1.1,2.2,1.1), .Label=c("a", "b"), class = c('factor')); x } +[1] a b a +Levels: a b + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-structure(c(1.2,2.2,1.1), .Label=c("a", "b"), class = c('factor')); x } +[1] a b a +Levels: a b + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-structure(c(2.2,3.2,2.1), .Label=c("a", "b"), class = c('factor')); as.integer(x) } +[1] 2 3 2 + +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor +#{ x<-structure(factor(c("a","b","c")), class=NULL); x } +[1] 1 2 3 +attr(,"levels") +[1] "a" "b" "c" + ##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFactor #{data = c(1,2,2,3,1,2,3,3,1,2,3,3,1);fdata<-factor(data);levels(fdata) = c('I','II','III');print(fdata);} [1] I II II III I II III III I II III III I @@ -16315,6 +16455,32 @@ $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.testMisc +#{ y<-data.frame(7); as.logical(y) } +[1] TRUE + +##com.oracle.truffle.r.test.simple.TestSimpleDataFrames.testMisc +#{ y<-data.frame(c(1,2,3)); as.logical(y) } +Error: (list) object cannot be coerced to type 'logical' + +##com.oracle.truffle.r.test.simple.TestSimpleDataFrames.testMisc +#{ y<-data.frame(integer()); as.logical(y) } +[1] NA + +##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 @@ -16332,6 +16498,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 @@ -17029,6 +17202,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 aa5c62f0f6c9f80729d29bf7413dbb9e8ac9f1a3..3546d4f0fb34d477391964a3af346ae9aed0c00e 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 @@ -8158,6 +8158,101 @@ public class AllTests extends TestBase { assertEval("{ x<-factor(c(\"a\", \"b\", \"a\", \"c\")); x == c(\"a\", \"b\") }"); } + @Test + public void TestSimpleBuiltins_testFactor_c6b2929aec56f236a9015269d6d5e6f0() { + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\"), ordered=TRUE); x > \"a\" }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_e759d4fccb890277ccc9ddb8fcb0dec3() { + assertEval("{ x<-c(1L, 2L, 1L); class(x)<-c(\"ordered\", \"factor\"); levels(x)<-c(\"a\", \"b\"); x > \"a\" }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_9383599e2b32f549f5e46351c2e6bd9b() { + assertEval("{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-list(1); y[[1]]<-x; y }"); + } + + @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_fdae08cc3544f4e5c971d2303a796eeb() { + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); is.atomic(x) }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_5302c7a50fda26503b5d1f681cec279c() { + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\"), ordered=TRUE); is.atomic(x) }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_a8153cc5be539920818caa4f7d546190() { + assertEval("{ as.logical(factor(c(\"a\", \"b\", \"a\"))) }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_19ca5910d2b0103d936cfdd499387aa2() { + assertEval("{ as.logical(factor(integer())) }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_efa5f97d32564f78732db53e6862362e() { + assertEval("{ x<-structure(c(1.1,2.2,1.1), .Label=c(\"a\", \"b\"), class = c('factor')); attributes(x) }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_d5fd844e772c2e96c1266f8c4e181e7a() { + assertEval("{ x<-structure(c(1.1,2.2,1.1), .Label=c(\"a\", \"b\"), class = c('factor')); x }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_69974a637dd01d933a0274513b334646() { + assertEval("{ x<-structure(c(1.2,2.2,1.1), .Label=c(\"a\", \"b\"), class = c('factor')); x }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_1d6da35b510c64fda496cd4d92b0b8dd() { + assertEval("{ x<-structure(c(2.2,3.2,2.1), .Label=c(\"a\", \"b\"), class = c('factor')); as.integer(x) }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_c97bd5071d6a70f07678a33414644e52() { + assertEval("{ x<-structure(c(1,2,1), .Label=c(\"a\", \"b\"), class = c('factor'), .Names=c(\"111\",\"112\",\"113\")); y<-structure(c(1,2,1), .Label=c(\"a\", \"b\"), class = c('factor'), .Names=c(\"111\",\"112\",\"113\")); x==y }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_a87228cb9283d7ba484ab0b60059e1bf() { + assertEval("{ x<-structure(factor(c(\"a\",\"b\",\"c\")), class=NULL); x }"); + } + @Test public void TestSimpleBuiltins_testFactor_2ef7de52def309425a9b70965111f004() { assertEvalError("{ x<-c(1,2,3); class(x)<-\"factor\"; x }"); @@ -8173,14 +8268,19 @@ public class AllTests extends TestBase { assertEvalError("{ x<-c(1L,2L,3L); class(x)<-\"factor\"; x }"); } + @Test + public void TestSimpleBuiltins_testFactor_778d87ada7ac057126f8a27cfe882a81() { + assertEvalError("{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-c(1); y[[1]]<-x; y }"); + } + @Test public void TestSimpleBuiltins_testFactor_8e866be378d6495f8d649996dcb5bb3c() { - assertEvalError("{ x<-factor(c(\"a\", \"b\", \"a\")); x > \"a\" }"); + assertEvalWarning("{ x<-factor(c(\"a\", \"b\", \"a\")); x > \"a\" }"); } @Test - public void TestSimpleBuiltins_testFactor_7cd2b27121f6c77b417a436d60108819() { - assertEvalError("{ x<-factor(c(\"a\", \"b\", \"a\")); x > c(\"a\", \"b\") }"); + public void TestSimpleBuiltins_testFactor_cab09968ee0783bc157730e05358ed0c() { + assertEvalWarning("{ x<-factor(c(\"a\", \"b\", \"a\")); x + \"a\" }"); } @Test @@ -8188,6 +8288,36 @@ public class AllTests extends TestBase { assertEvalWarning("{ x<-factor(c(\"a\", \"b\", \"a\")); x == c(\"a\", \"b\") }"); } + @Test + public void TestSimpleBuiltins_testFactor_7cd2b27121f6c77b417a436d60108819() { + assertEvalWarning("{ x<-factor(c(\"a\", \"b\", \"a\")); x > c(\"a\", \"b\") }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_a34678ac5082e00e15dd97ecd53f0e12() { + assertEvalWarning("{ x<-factor(c(\"a\", \"b\", \"a\")); x + c(\"a\", \"b\") }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_7b9d1da1c475fe180c3d19653a62003e() { + assertEvalWarning("{ x<-factor(c(\"a\", \"b\", \"a\"), ordered=TRUE); x + \"a\" }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_e1f4890b0e585468d589f92e64e8fe43() { + assertEvalWarning("{ x<-c(1L, 2L, 1L); class(x)<-c(\"factor\", \"ordered\"); levels(x)<-c(\"a\", \"b\"); x > \"a\" }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_442949c79222d476ad19ed8d25f6d67b() { + assertEvalWarning("{ x<-c(1L, 2L, 1L); class(x)<-c(\"ordered\", \"factor\"); levels(x)<-c(\"a\", \"b\"); x + \"a\" }"); + } + + @Test + public void TestSimpleBuiltins_testFactor_b998c6b80f80df4ef39a60ff889bc0e4() { + assertEvalWarning("{ x<-c(1L, 2L, 1L); class(x)<-c(\"factor\", \"ordered\"); levels(x)<-c(\"a\", \"b\"); x + \"a\" }"); + } + @Test public void TestSimpleBuiltins_testFactor_9b48b1721b63ffee900121993a15bb82() { assertEvalWarning("{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-list(1); y[1]<-x; y }"); @@ -8198,6 +8328,11 @@ public class AllTests extends TestBase { assertEvalWarning("{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-c(1); y[1]<-x; y }"); } + @Test + public void TestSimpleBuiltins_testFactor_79abe62e1800fec0bdfb1ee89b43889b() { + assertEvalWarning("{ x<-structure(c(1,2,1), .Label=c(\"a\", \"b\"), class = c('factor'), .Names=c(\"111\",\"112\",\"113\")); y<-structure(c(1,2,1), .Label=c(\"a\", \"b\"), class = c('factor'), .Names=c(\"111\",\"112\",\"113\")); x+y }"); + } + @Test public void TestSimpleBuiltins_testFileListing_9646bfd3fb553824f1f54cc5d04b8219() { assertEval("{ list.files(\"test/r/simple/data/tree1\") }"); @@ -17128,6 +17263,26 @@ 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_testMisc_e52a62b09e6557563b89aed7622a090f() { + assertEval("{ y<-data.frame(7); as.logical(y) }"); + } + + @Test + public void TestSimpleDataFrames_testMisc_41c31f4873ee11a67409c7646ea787b9() { + assertEval("{ y<-data.frame(integer()); as.logical(y) }"); + } + + @Test + public void TestSimpleDataFrames_testMisc_526983ed080a1f64591401d75eba5c80() { + assertEvalError("{ y<-data.frame(c(1,2,3)); as.logical(y) }"); + } + @Test public void TestSimpleDataFrames_testPrint_da9c92f6582f469a3303b14bf936c77e() { assertEval("{x<-c(1,2); class(x)<-\"data.frame\"; x}"); @@ -17153,6 +17308,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) }"); @@ -18023,6 +18188,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 7b5a43f148d77d29f37939bee478b7a489524141..1a6704c9ddf422596c63afadf8cdc6d979e29557 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 @@ -3902,14 +3902,49 @@ public class TestSimpleBuiltins extends TestBase { assertEvalError("{ x<-c(1L,2L,3L); class(x)<-\"factor\"; x }"); assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); x == \"a\" }"); - assertEvalError("{ x<-factor(c(\"a\", \"b\", \"a\")); x > \"a\" }"); + assertEvalWarning("{ x<-factor(c(\"a\", \"b\", \"a\")); x > \"a\" }"); + assertEvalWarning("{ x<-factor(c(\"a\", \"b\", \"a\")); x + \"a\" }"); assertEvalWarning("{ x<-factor(c(\"a\", \"b\", \"a\")); x == c(\"a\", \"b\") }"); - assertEvalError("{ x<-factor(c(\"a\", \"b\", \"a\")); x > c(\"a\", \"b\") }"); + assertEvalWarning("{ x<-factor(c(\"a\", \"b\", \"a\")); x > c(\"a\", \"b\") }"); + assertEvalWarning("{ x<-factor(c(\"a\", \"b\", \"a\")); x + c(\"a\", \"b\") }"); assertEval("{ x<-factor(c(\"a\", \"b\", \"a\", \"c\")); x == c(\"a\", \"b\") }"); + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\"), ordered=TRUE); x > \"a\" }"); + assertEvalWarning("{ x<-factor(c(\"a\", \"b\", \"a\"), ordered=TRUE); x + \"a\" }"); + + assertEval("{ x<-c(1L, 2L, 1L); class(x)<-c(\"ordered\", \"factor\"); levels(x)<-c(\"a\", \"b\"); x > \"a\" }"); + assertEvalWarning("{ x<-c(1L, 2L, 1L); class(x)<-c(\"factor\", \"ordered\"); levels(x)<-c(\"a\", \"b\"); x > \"a\" }"); + assertEvalWarning("{ x<-c(1L, 2L, 1L); class(x)<-c(\"ordered\", \"factor\"); levels(x)<-c(\"a\", \"b\"); x + \"a\" }"); + assertEvalWarning("{ x<-c(1L, 2L, 1L); class(x)<-c(\"factor\", \"ordered\"); levels(x)<-c(\"a\", \"b\"); x + \"a\" }"); 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(\"c\", \"b\", \"a\", \"c\")); y<-list(1); y[[1]]<-x; y }"); + assertEvalError("{ 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)] }"); + + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); is.atomic(x) }"); + assertEval("{ x<-factor(c(\"a\", \"b\", \"a\"), ordered=TRUE); is.atomic(x) }"); + + assertEval("{ as.logical(factor(c(\"a\", \"b\", \"a\"))) }"); + assertEval("{ as.logical(factor(integer())) }"); + + assertEval("{ x<-structure(c(1.1,2.2,1.1), .Label=c(\"a\", \"b\"), class = c('factor')); attributes(x) }"); + assertEval("{ x<-structure(c(1.1,2.2,1.1), .Label=c(\"a\", \"b\"), class = c('factor')); x }"); + assertEval("{ x<-structure(c(1.2,2.2,1.1), .Label=c(\"a\", \"b\"), class = c('factor')); x }"); + assertEval("{ x<-structure(c(2.2,3.2,2.1), .Label=c(\"a\", \"b\"), class = c('factor')); as.integer(x) }"); + + assertEval("{ x<-structure(c(1,2,1), .Label=c(\"a\", \"b\"), class = c('factor'), .Names=c(\"111\",\"112\",\"113\")); y<-structure(c(1,2,1), .Label=c(\"a\", \"b\"), class = c('factor'), .Names=c(\"111\",\"112\",\"113\")); x==y }"); + assertEvalWarning("{ x<-structure(c(1,2,1), .Label=c(\"a\", \"b\"), class = c('factor'), .Names=c(\"111\",\"112\",\"113\")); y<-structure(c(1,2,1), .Label=c(\"a\", \"b\"), class = c('factor'), .Names=c(\"111\",\"112\",\"113\")); x+y }"); + + assertEval("{ x<-structure(factor(c(\"a\",\"b\",\"c\")), class=NULL); x }"); + } @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 2ec6c750bab29350b5bb620df8ff9112162ff9cd..feb33af1adae8cd05320fbf4f24dfeb522aa0237 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,15 @@ 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 }"); + + assertEval("{ y<-data.frame(7); as.logical(y) }"); + assertEval("{ y<-data.frame(integer()); as.logical(y) }"); + assertEvalError("{ y<-data.frame(c(1,2,3)); as.logical(y) }"); + + } + } 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 b054e012279b9cbea86c91e3d9f510e3b93074dc..67de58daf94189c30512c12a33f8df7bd83dd95a 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 diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides index ae129fa904741d4c8d7e26e63c07b3cc4456613a..6ac47a08e131939ad2457537ccd4b71f1dce69da 100644 --- a/mx.fastr/copyrights/overrides +++ b/mx.fastr/copyrights/overrides @@ -67,7 +67,8 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/stats/ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/stats/Rnorm.java,gnu_r.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/stats/StatsUtil.java,gnu_r_statsutil.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/CountFields.java,gnu_r.copyright -com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/UtilsPackage.java,purdue.copyright +com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/CountFields.java,gnu_r.copyright +com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/WriteTable.java,gnu_r.copyright com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParseException.java,purdue.copyright com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParseUtil.java,purdue.copyright com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g,purdue.copyright