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 690be3687739064daaffa07a9931b00cedbf6257..8ff47c9a33d5c608a49508dc26d528ee4b514ab5 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 @@ -33,6 +33,7 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RDispatch; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; @@ -43,7 +44,7 @@ public abstract class AsDouble extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(AsDouble.class); - casts.arg("x").returnIf(missingValue().or(nullValue()), emptyDoubleVector()).asDoubleVector(); + casts.arg("x").defaultWarningContext(RError.NO_CALLER).returnIf(missingValue().or(nullValue()), emptyDoubleVector()).asDoubleVector(); } @Specialization(guards = "reuseTemporaryNode.supports(v)", limit = "getVectorAccessCacheSize()") 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 d83313df5838e4167e85b110ecdbc0c19f7c8e89..b157eb8f052b1e82a6540d1672a7e097dbd4ed55 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 @@ -33,6 +33,7 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; @@ -43,7 +44,7 @@ public abstract class AsLogical extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(AsLogical.class); - casts.arg("x").returnIf(missingValue().or(nullValue()), emptyLogicalVector()).asLogicalVector(); + casts.arg("x").defaultWarningContext(RError.NO_CALLER).returnIf(missingValue().or(nullValue()), emptyLogicalVector()).asLogicalVector(); } @Specialization(guards = "reuseTemporaryNode.supports(v)", limit = "getVectorAccessCacheSize()") diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java index d71d282770bc1a4adeefdd769f6388b04b65fb7f..ba0d5efa556a6ae879b8f0b60229ac8d758ce20f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java @@ -43,7 +43,7 @@ public abstract class AsRaw extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(AsRaw.class); - casts.arg("x").mustBe(missingValue().not(), RError.Message.ARGUMENTS_PASSED, 0, "'as.raw'", 1).asRawVector(); + casts.arg("x").defaultWarningContext(RError.NO_CALLER).mustBe(missingValue().not(), RError.Message.ARGUMENTS_PASSED, 0, "'as.raw'", 1).asRawVector(); } @Specialization diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java index 7c8a2db5b90a8d2364f7d1a49de2aeabe79cedbc..9ba7314e4f22c0ffcf99d460e66d1d2cf25c1f89 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java @@ -237,18 +237,18 @@ public final class PipelineToCastNode { return step.vectorCoercion ? CastIntegerNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure, warningContext) : CastIntegerBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure, warningContext); case Double: - return step.vectorCoercion ? CastDoubleNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure) - : CastDoubleBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure); + return step.vectorCoercion ? CastDoubleNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure, warningContext) + : CastDoubleBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure, warningContext); case Character: - return step.vectorCoercion ? CastStringNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, false, warningContext) - : CastStringBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, false, warningContext); + return step.vectorCoercion ? CastStringNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure, warningContext) + : CastStringBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure, warningContext); case Logical: - return step.vectorCoercion ? CastLogicalNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes) - : CastLogicalBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); + return step.vectorCoercion ? CastLogicalNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure, warningContext) + : CastLogicalBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure, warningContext); case Complex: - return CastComplexNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, warningContext); + return CastComplexNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.useClosure, warningContext); case Raw: - return CastRawNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); + return CastRawNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.useClosure, step.useClosure, warningContext); case Any: return CastToVectorNodeGen.create(step.preserveNonVector); default: diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java index 320147333f13418bb72f9e8a7f61994f4f57463c..dee35f5efb184f4ed4da4bdd1b1346d951cd58ff 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java @@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.runtime.RError.ErrorContext; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; @@ -32,13 +33,13 @@ import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRaw; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess; import com.oracle.truffle.r.runtime.ops.na.NACheck; import com.oracle.truffle.r.runtime.ops.na.NAProfile; public abstract class CastDoubleBaseNode extends CastBaseNode { protected final NACheck naCheck = NACheck.create(); - protected final NAProfile naProfile = NAProfile.create(); protected CastDoubleBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { super(preserveNames, preserveDimensions, preserveAttributes); @@ -48,6 +49,10 @@ public abstract class CastDoubleBaseNode extends CastBaseNode { super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, useClosure); } + protected CastDoubleBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean useClosure, ErrorContext warningContext) { + super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, useClosure, warningContext); + } + @Override protected final RType getTargetType() { return RType.Double; @@ -82,14 +87,18 @@ public abstract class CastDoubleBaseNode extends CastBaseNode { return operand; } - @Specialization - protected double doDouble(RComplex operand) { - naCheck.enable(operand); - double result = naCheck.convertComplexToDouble(operand, false); - if (operand.getImaginaryPart() != 0.0) { - warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); + @Specialization(guards = "uAccess.supports(operand)", limit = "getVectorAccessCacheSize()") + protected double doComplex(RComplex operand, + @Cached("operand.access()") VectorAccess uAccess) { + try (VectorAccess.SequentialIterator sIter = uAccess.access(operand, warningContext())) { + uAccess.next(sIter); + return uAccess.getDouble(sIter); } - return result; + } + + @Specialization(replaces = "doComplex") + protected double doComplexGeneric(RComplex operand) { + return doComplex(operand, operand.slowPathAccess()); } @Specialization @@ -100,13 +109,14 @@ public abstract class CastDoubleBaseNode extends CastBaseNode { @Specialization protected double doString(String operand, - @Cached("createBinaryProfile()") ConditionProfile emptyStringProfile) { + @Cached("createBinaryProfile()") ConditionProfile emptyStringProfile, + @Cached("create()") NAProfile naProfile) { if (naProfile.isNA(operand) || emptyStringProfile.profile(operand.isEmpty())) { return RRuntime.DOUBLE_NA; } double result = RRuntime.string2doubleNoCheck(operand); if (RRuntime.isNA(result)) { - warning(RError.Message.NA_INTRODUCED_COERCION); + warning(warningContext() != null ? warningContext() : null, RError.Message.NA_INTRODUCED_COERCION); } return result; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java index 34461d559e36ddfa3d3a9f4165a3b74af38f8ed7..3f99a6672ab2a45750b78396d70fd7a3089c489c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java @@ -22,20 +22,17 @@ */ package com.oracle.truffle.r.nodes.unary; -import java.util.function.IntToDoubleFunction; - import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.TruffleObject; -import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.runtime.DSLConfig; import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.ErrorContext; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RForeignBooleanWrapper; import com.oracle.truffle.r.runtime.data.RForeignIntWrapper; @@ -44,20 +41,24 @@ import com.oracle.truffle.r.runtime.data.RForeignWrapper; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.closures.RClosures; +import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.SequentialIterator; import com.oracle.truffle.r.runtime.interop.ForeignArray2R; +import com.oracle.truffle.r.runtime.ops.na.NAProfile; -@ImportStatic(RRuntime.class) +@ImportStatic({RRuntime.class, DSLConfig.class}) public abstract class CastDoubleNode extends CastDoubleBaseNode { + protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean withReuse, ErrorContext warningContext) { + super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, withReuse, warningContext); + } + protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean withReuse) { super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, withReuse); } @@ -84,100 +85,36 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { return ret; } - private RDoubleVector createResultVector(RAbstractVector operand, IntToDoubleFunction elementFunction) { - naCheck.enable(operand); - double[] ddata = new double[operand.getLength()]; - boolean seenNA = false; - for (int i = 0; i < operand.getLength(); i++) { - double value = elementFunction.applyAsDouble(i); - ddata[i] = value; - seenNA = seenNA || naProfile.isNA(value); - } - return vectorCopy(operand, ddata, !seenNA); - } - - @Specialization(guards = "!isForeignWrapper(x)") - protected RAbstractDoubleVector doIntVector(RAbstractIntVector x, - @Cached("createClassProfile()") ValueProfile operandTypeProfile) { - RAbstractIntVector operand = operandTypeProfile.profile(x); - if (useClosure()) { - return (RAbstractDoubleVector) castWithReuse(RType.Double, operand, naProfile.getConditionProfile()); + private RDoubleVector createResultVector(RAbstractAtomicVector operand, VectorAccess uAccess) { + double[] idata = new double[operand.getLength()]; + try (VectorAccess.SequentialIterator sIter = uAccess.access(operand, warningContext())) { + while (uAccess.next(sIter)) { + idata[sIter.getIndex()] = uAccess.getDouble(sIter); + } } - return createResultVector(operand, index -> naCheck.convertIntToDouble(operand.getDataAt(index))); + return vectorCopy(operand, idata, uAccess.na.neverSeenNAOrNaN()); } - @Specialization(guards = "!isForeignWrapper(x)") - protected RAbstractDoubleVector doLogicalVector(RAbstractLogicalVector x, - @Cached("createClassProfile()") ValueProfile operandTypeProfile) { - RAbstractLogicalVector operand = operandTypeProfile.profile(x); - if (useClosure()) { - return (RAbstractDoubleVector) castWithReuse(RType.Double, operand, naProfile.getConditionProfile()); - } - return createResultVector(operand, index -> naCheck.convertLogicalToDouble(operand.getDataAt(index))); + @Specialization(guards = {"uAccess.supports(x)", "noClosure(x)"}, limit = "getGenericVectorAccessCacheSize()") + protected RAbstractDoubleVector doAbstractVector(RAbstractAtomicVector x, + @Cached("createClassProfile()") ValueProfile operandTypeProfile, + @Cached("x.access()") VectorAccess uAccess) { + RAbstractAtomicVector operand = operandTypeProfile.profile(x); + return createResultVector(operand, uAccess); } - @Specialization - protected RAbstractDoubleVector doRawVector(RAbstractRawVector x, + @Specialization(replaces = "doAbstractVector", guards = "noClosure(x)") + protected RAbstractDoubleVector doAbstractVectorGeneric(RAbstractAtomicVector x, @Cached("createClassProfile()") ValueProfile operandTypeProfile) { - RAbstractRawVector operand = operandTypeProfile.profile(x); - if (useClosure()) { - return (RAbstractDoubleVector) castWithReuse(RType.Double, operand, naProfile.getConditionProfile()); - } - return createResultVector(operand, index -> RRuntime.raw2double(operand.getRawDataAt(index))); - } - - @Specialization(guards = "!isForeignWrapper(operand)") - protected RDoubleVector doStringVector(RAbstractStringVector operand, - @Cached("createBinaryProfile()") ConditionProfile emptyStringProfile, - @Cached("create()") BranchProfile warningBranch) { - naCheck.enable(operand); - double[] ddata = new double[operand.getLength()]; - boolean seenNA = false; - boolean warning = false; - for (int i = 0; i < operand.getLength(); i++) { - String value = operand.getDataAt(i); - double doubleValue; - if (naCheck.check(value) || emptyStringProfile.profile(value.isEmpty())) { - doubleValue = RRuntime.DOUBLE_NA; - seenNA = true; - } else { - doubleValue = RRuntime.string2doubleNoCheck(value); - if (naProfile.isNA(doubleValue)) { - seenNA = true; - if (!value.isEmpty()) { - warningBranch.enter(); - warning = true; - } - } - } - ddata[i] = doubleValue; - } - if (warning) { - warning(RError.Message.NA_INTRODUCED_COERCION); - } - RDoubleVector ret = factory().createDoubleVector(ddata, !seenNA, getPreservedDimensions(operand), getPreservedNames(operand), getPreservedDimNames(operand)); - if (preserveRegAttributes()) { - ret.copyRegAttributesFrom(operand); - } - return ret; + return doAbstractVector(x, operandTypeProfile, x.slowPathAccess()); } - @Specialization - protected RDoubleVector doComplexVector(RAbstractComplexVector operand) { - naCheck.enable(operand); - double[] ddata = new double[operand.getLength()]; - boolean warning = false; - for (int i = 0; i < operand.getLength(); i++) { - RComplex value = operand.getDataAt(i); - ddata[i] = naCheck.convertComplexToDouble(value, false); - if (value.getImaginaryPart() != 0.0) { - warning = true; - } - } - if (warning) { - warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); - } - return vectorCopy(operand, ddata, naCheck.neverSeenNA()); + @Specialization(guards = {"useClosure(x)"}) + public RAbstractDoubleVector doAbstractVectorClosure(RAbstractAtomicVector x, + @Cached("createClassProfile()") ValueProfile operandTypeProfile, + @Cached("create()") NAProfile naProfile) { + RAbstractAtomicVector operand = operandTypeProfile.profile(x); + return (RAbstractDoubleVector) castWithReuse(RType.Double, operand, naProfile.getConditionProfile()); } @Specialization @@ -185,36 +122,40 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { return operand; } - @Specialization - protected RDoubleVector doList(RAbstractListVector list) { + @Specialization(guards = "uAccess.supports(list)", limit = "getVectorAccessCacheSize()") + protected RDoubleVector doList(RAbstractListVector list, + @Cached("list.access()") VectorAccess uAccess) { int length = list.getLength(); double[] result = new double[length]; boolean seenNA = false; - for (int i = 0; i < length; i++) { - Object entry = list.getDataAt(i); - if (entry instanceof RList) { - result[i] = RRuntime.DOUBLE_NA; - seenNA = true; - } else { - Object castEntry = castDoubleRecursive(entry); - if (castEntry instanceof Double) { - double value = (Double) castEntry; - result[i] = value; - seenNA = seenNA || RRuntime.isNA(value); - } else if (castEntry instanceof RDoubleVector) { - RDoubleVector doubleVector = (RDoubleVector) castEntry; - if (doubleVector.getLength() == 1) { - double value = doubleVector.getDataAt(0); + try (SequentialIterator sIter = uAccess.access(list, warningContext())) { + while (uAccess.next(sIter)) { + int i = sIter.getIndex(); + Object entry = uAccess.getListElement(sIter); + if (entry instanceof RList) { + result[i] = RRuntime.DOUBLE_NA; + seenNA = true; + } else { + Object castEntry = castDoubleRecursive(entry); + if (castEntry instanceof Double) { + double value = (Double) castEntry; result[i] = value; seenNA = seenNA || RRuntime.isNA(value); - } else if (doubleVector.getLength() == 0) { - result[i] = RRuntime.DOUBLE_NA; - seenNA = true; + } else if (castEntry instanceof RDoubleVector) { + RDoubleVector doubleVector = (RDoubleVector) castEntry; + if (doubleVector.getLength() == 1) { + double value = doubleVector.getDataAt(0); + result[i] = value; + seenNA = seenNA || RRuntime.isNA(value); + } else if (doubleVector.getLength() == 0) { + result[i] = RRuntime.DOUBLE_NA; + seenNA = true; + } else { + throw throwCannotCoerceListError("numeric"); + } } else { throw throwCannotCoerceListError("numeric"); } - } else { - throw throwCannotCoerceListError("numeric"); } } } @@ -225,9 +166,14 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { return ret; } + @Specialization(replaces = "doList") + protected RDoubleVector doListGeneric(RAbstractListVector list) { + return doList(list, list.slowPathAccess()); + } + @Specialization(guards = "!pairList.isLanguage()") protected RDoubleVector doPairList(RPairList pairList) { - return doList(pairList.toRList()); + return (RDoubleVector) castDoubleRecursive(pairList.toRList()); } @Specialization(guards = "isForeignObject(obj)") @@ -280,4 +226,12 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { public static CastDoubleNode createNonPreserving() { return CastDoubleNodeGen.create(false, false, false, false, false); } + + protected boolean useClosure(RAbstractAtomicVector x) { + return useClosure() && !isForeignWrapper(x) && !(x instanceof RAbstractDoubleVector) && !(x instanceof RAbstractStringVector || x instanceof RAbstractComplexVector); + } + + protected boolean noClosure(RAbstractAtomicVector x) { + return !isForeignWrapper(x) && !(x instanceof RAbstractDoubleVector) && (!useClosure() || x instanceof RAbstractStringVector || x instanceof RAbstractComplexVector); + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java index 486d8071a80c14efe50fcc4602b443bf1772670c..ff751fb600ae71324c743746d006d8df14f9df59 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java @@ -241,10 +241,10 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { } protected boolean useClosure(RAbstractAtomicVector x) { - return !isForeignWrapper(x) && useClosure() && !(x instanceof RAbstractStringVector || x instanceof RAbstractComplexVector); + return useClosure() && !isForeignWrapper(x) && !(x instanceof RAbstractIntVector) && !(x instanceof RAbstractStringVector || x instanceof RAbstractComplexVector); } protected boolean noClosure(RAbstractAtomicVector x) { - return !isForeignWrapper(x) && (!useClosure() || x instanceof RAbstractStringVector || x instanceof RAbstractComplexVector); + return !isForeignWrapper(x) && !(x instanceof RAbstractIntVector) && (!useClosure() || x instanceof RAbstractStringVector || x instanceof RAbstractComplexVector); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java index fa62efa2653e2edaab589f24187064a289f13bf0..c7dbb24162100635383ee9453be6925d1028111a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java @@ -27,6 +27,7 @@ import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.runtime.DSLConfig; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RExternalPtr; @@ -38,10 +39,12 @@ import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RS4Object; import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.SequentialIterator; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.interop.ForeignArray2R; -@ImportStatic(RRuntime.class) +@ImportStatic({RRuntime.class, DSLConfig.class}) public abstract class CastListNode extends CastBaseNode { public abstract RList executeList(Object o); @@ -74,13 +77,17 @@ public abstract class CastListNode extends CastBaseNode { return factory().createList(new Object[]{operand}); } - @Specialization + @Specialization(guards = "uAccess.supports(operand)", limit = "getVectorAccessCacheSize()") protected RList doAbstractVector(RAbstractVector operand, + @Cached("operand.access()") VectorAccess uAccess, @Cached("createClassProfile()") ValueProfile vectorClassProfile) { RAbstractVector profiledOperand = vectorClassProfile.profile(operand); Object[] data = new Object[profiledOperand.getLength()]; - for (int i = 0; i < data.length; i++) { - data[i] = profiledOperand.getDataAtAsObject(i); + + try (SequentialIterator sIter = uAccess.access(profiledOperand, warningContext())) { + while (uAccess.next(sIter)) { + data[sIter.getIndex()] = uAccess.getListElement(sIter); + } } RList ret = factory().createList(data, getPreservedDimensions(operand), getPreservedNames(operand), getPreservedDimNames(operand)); if (preserveRegAttributes()) { @@ -89,6 +96,12 @@ public abstract class CastListNode extends CastBaseNode { return ret; } + @Specialization(replaces = "doAbstractVector") + protected RList doAbstractVectorGeneric(RAbstractVector operand, + @Cached("createClassProfile()") ValueProfile vectorClassProfile) { + return doAbstractVector(operand, operand.slowPathAccess(), vectorClassProfile); + } + @Specialization protected RList doPairList(RPairList pl) { return pl.toRList(); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalBaseNode.java index 5ec1dfc078dd6687e3c8ec00487924311547b3e3..d3a723f2e94dd7fa6daf32332a9165ac0f8015fc 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalBaseNode.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.runtime.RError.ErrorContext; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RComplex; @@ -33,6 +34,10 @@ public abstract class CastLogicalBaseNode extends CastBaseNode { protected final NACheck naCheck = NACheck.create(); + protected CastLogicalBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean useClosure, ErrorContext warningContext) { + super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, useClosure, warningContext); + } + protected CastLogicalBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) { super(preserveNames, preserveDimensions, preserveAttributes, forRFFI); } 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 0397b7f612bba118adff4de92c2d03f58c1fd3ef..ed21db3395f5bedf7589f9524cc1da94a81c842a 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 @@ -30,7 +30,9 @@ import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode; +import com.oracle.truffle.r.runtime.DSLConfig; import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.ErrorContext; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RList; @@ -38,22 +40,18 @@ import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPairList; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.SequentialIterator; import com.oracle.truffle.r.runtime.interop.ForeignArray2R; -import com.oracle.truffle.r.runtime.ops.na.NAProfile; -@ImportStatic(RRuntime.class) +@ImportStatic({RRuntime.class, DSLConfig.class}) public abstract class CastLogicalNode extends CastLogicalBaseNode { - private final NAProfile naProfile = NAProfile.create(); - @Child private CastLogicalNode recursiveCastLogical; @Child private InheritsCheckNode inheritsFactorCheck; @@ -65,6 +63,10 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { super(preserveNames, preserveDimensions, preserveAttributes, forRFFI); } + protected CastLogicalNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean useClosure, ErrorContext warningContext) { + super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, useClosure, warningContext); + } + protected Object castLogicalRecursive(Object o) { if (recursiveCastLogical == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -73,24 +75,11 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { return recursiveCastLogical.execute(o); } - protected boolean isFactor(Object o) { - if (inheritsFactorCheck == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - inheritsFactorCheck = insert(new InheritsCheckNode(RRuntime.CLASS_FACTOR)); - } - return inheritsFactorCheck.execute(o); - } - @Specialization protected RNull doNull(@SuppressWarnings("unused") RNull operand) { return RNull.instance; } - @FunctionalInterface - private interface IntToByteFunction { - byte apply(int value); - } - private RLogicalVector vectorCopy(RAbstractVector operand, byte[] bdata, boolean isComplete) { RLogicalVector ret = factory().createLogicalVector(bdata, isComplete, getPreservedDimensions(operand), getPreservedNames(operand), getPreservedDimNames(operand)); if (preserveRegAttributes()) { @@ -99,16 +88,14 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { return ret; } - private RLogicalVector createResultVector(RAbstractVector operand, IntToByteFunction elementFunction) { - naCheck.enable(operand); + private RLogicalVector createResultVector(RAbstractVector operand, VectorAccess uAccess) { byte[] bdata = new byte[operand.getLength()]; - boolean seenNA = false; - for (int i = 0; i < operand.getLength(); i++) { - byte value = elementFunction.apply(i); - bdata[i] = value; - seenNA = seenNA || naProfile.isNA(value); + try (SequentialIterator sIter = uAccess.access(operand, warningContext())) { + while (uAccess.next(sIter)) { + bdata[sIter.getIndex()] = uAccess.getLogical(sIter); + } } - return vectorCopy(operand, bdata, !seenNA); + return vectorCopy(operand, bdata, uAccess.na.neverSeenNAOrNaN()); } @Specialization @@ -116,9 +103,15 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { return operand; } - @Specialization(guards = "!isFactor(operand)") - protected RLogicalVector doIntVector(RAbstractIntVector operand) { - return createResultVector(operand, index -> naCheck.convertIntToLogical(operand.getDataAt(index))); + @Specialization(guards = {"uAccess.supports(operand)", "useVectorAccess(operand)"}, limit = "getGenericVectorAccessCacheSize()") + protected RLogicalVector doAbstractVector(RAbstractAtomicVector operand, + @Cached("operand.access()") VectorAccess uAccess) { + return createResultVector(operand, uAccess); + } + + @Specialization(replaces = "doAbstractVector", guards = {"useVectorAccess(operand)"}) + protected RLogicalVector doAbstractVectorGeneric(RAbstractAtomicVector operand) { + return createResultVector(operand, operand.slowPathAccess()); } @Specialization(guards = "isFactor(factor)") @@ -128,56 +121,40 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { return factory().createLogicalVector(data, RDataFactory.INCOMPLETE_VECTOR); } - @Specialization - protected RLogicalVector doDoubleVector(RAbstractDoubleVector operand) { - return createResultVector(operand, index -> naCheck.convertDoubleToLogical(operand.getDataAt(index))); - } - - @Specialization - protected RLogicalVector doStringVector(RAbstractStringVector operand) { - return createResultVector(operand, index -> naCheck.convertStringToLogical(operand.getDataAt(index))); - } - - @Specialization - protected RLogicalVector doComplexVector(RAbstractComplexVector operand) { - return createResultVector(operand, index -> naCheck.convertComplexToLogical(operand.getDataAt(index))); - } - - @Specialization - protected RLogicalVector doRawVectorDims(RAbstractRawVector operand) { - return createResultVector(operand, index -> RRuntime.raw2logical(operand.getRawDataAt(index))); - } - - @Specialization - protected RLogicalVector doList(RAbstractListVector list) { + @Specialization(guards = "uAccess.supports(list)", limit = "getVectorAccessCacheSize()") + protected RLogicalVector doList(RAbstractListVector list, + @Cached("list.access()") VectorAccess uAccess) { int length = list.getLength(); byte[] result = new byte[length]; boolean seenNA = false; - for (int i = 0; i < length; i++) { - Object entry = list.getDataAt(i); - if (entry instanceof RList) { - result[i] = RRuntime.LOGICAL_NA; - seenNA = true; - } else { - Object castEntry = castLogicalRecursive(entry); - if (castEntry instanceof Byte) { - byte value = (Byte) castEntry; - result[i] = value; - seenNA = seenNA || RRuntime.isNA(value); - } else if (castEntry instanceof RLogicalVector) { - RLogicalVector logicalVector = (RLogicalVector) castEntry; - if (logicalVector.getLength() == 1) { - byte value = logicalVector.getDataAt(0); + try (SequentialIterator sIter = uAccess.access(list, warningContext())) { + while (uAccess.next(sIter)) { + int i = sIter.getIndex(); + Object entry = uAccess.getListElement(sIter); + if (entry instanceof RList) { + result[i] = RRuntime.LOGICAL_NA; + seenNA = true; + } else { + Object castEntry = castLogicalRecursive(entry); + if (castEntry instanceof Byte) { + byte value = (Byte) castEntry; result[i] = value; seenNA = seenNA || RRuntime.isNA(value); - } else if (logicalVector.getLength() == 0) { - result[i] = RRuntime.LOGICAL_NA; - seenNA = true; + } else if (castEntry instanceof RLogicalVector) { + RLogicalVector logicalVector = (RLogicalVector) castEntry; + if (logicalVector.getLength() == 1) { + byte value = logicalVector.getDataAt(0); + result[i] = value; + seenNA = seenNA || RRuntime.isNA(value); + } else if (logicalVector.getLength() == 0) { + result[i] = RRuntime.LOGICAL_NA; + seenNA = true; + } else { + throw throwCannotCoerceListError("logical"); + } } else { throw throwCannotCoerceListError("logical"); } - } else { - throw throwCannotCoerceListError("logical"); } } } @@ -188,9 +165,14 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { return ret; } + @Specialization(replaces = "doList") + protected RLogicalVector doListGeneric(RAbstractListVector list) { + return doList(list, list.slowPathAccess()); + } + @Specialization(guards = "!pairList.isLanguage()") protected RLogicalVector doPairList(RPairList pairList) { - return doList(pairList.toRList()); + return (RLogicalVector) castLogicalRecursive(pairList.toRList()); } @Specialization @@ -225,4 +207,19 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { public static CastLogicalNode createNonPreserving() { return CastLogicalNodeGen.create(false, false, false); } + + protected boolean isFactor(RAbstractIntVector o) { + if (inheritsFactorCheck == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + inheritsFactorCheck = insert(new InheritsCheckNode(RRuntime.CLASS_FACTOR)); + } + return inheritsFactorCheck.execute(o); + } + + protected boolean useVectorAccess(RAbstractAtomicVector x) { + if (x instanceof RAbstractIntVector && isFactor((RAbstractIntVector) x)) { + return false; + } + return !(x instanceof RAbstractLogicalVector); + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java index 2b8fca447aece3df6390f9748e4c7980091f4b19..33e255794271a51a6d6a033563952a4b8a9ee321 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java @@ -24,34 +24,32 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.runtime.DSLConfig; import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.ErrorContext; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -import com.oracle.truffle.r.runtime.ops.na.NACheck; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess; +import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.SequentialIterator; import com.oracle.truffle.r.runtime.ops.na.NAProfile; +@ImportStatic({DSLConfig.class}) public abstract class CastRawNode extends CastBaseNode { - private final NACheck naCheck = NACheck.create(); - private final BranchProfile warningBranch = BranchProfile.create(); - protected CastRawNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { this(preserveNames, preserveDimensions, preserveAttributes, false); } @@ -60,6 +58,10 @@ public abstract class CastRawNode extends CastBaseNode { super(preserveNames, preserveDimensions, preserveAttributes, forRFFI); } + protected CastRawNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean useClosures, ErrorContext warningContext) { + super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, useClosures, warningContext); + } + @Child private CastRawNode recursiveCastRaw; @Override @@ -95,7 +97,7 @@ public abstract class CastRawNode extends CastBaseNode { private RRaw checkOutOfRange(int operand, int intResult) { if (intResult != operand) { - warning(RError.Message.OUT_OF_RANGE); + warning(warningContext(), RError.Message.OUT_OF_RANGE); return factory().createRaw((byte) 0); } return factory().createRaw((byte) intResult); @@ -108,16 +110,41 @@ public abstract class CastRawNode extends CastBaseNode { } @Specialization - protected RRaw doDouble(double operand) { - int intResult = RRuntime.double2rawIntValue(operand); + protected RRaw doDouble(double operand, + @Cached("create()") NAProfile naProfile) { + int intResult; + if (naProfile.isNA(operand)) { + warning(warningContext(), RError.Message.OUT_OF_RANGE); + intResult = 0; + } else { + if (operand > Integer.MAX_VALUE || operand <= Integer.MIN_VALUE) { + intResult = 0; + warning(warningContext(), RError.Message.NA_INTRODUCED_COERCION_INT); + } else { + intResult = RRuntime.double2rawIntValue(operand); + } + } return checkOutOfRange((int) operand, intResult); } @Specialization - protected RRaw doComplex(RComplex operand) { - int intResult = RRuntime.complex2rawIntValue(operand); - if (operand.getImaginaryPart() != 0) { - warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); + protected RRaw doComplex(RComplex operand, + @Cached("create()") NAProfile naProfile) { + int intResult; + if (naProfile.isNA(operand)) { + warning(warningContext(), RError.Message.OUT_OF_RANGE); + intResult = 0; + } else { + double realPart = operand.getRealPart(); + if (realPart > Integer.MAX_VALUE || realPart <= Integer.MIN_VALUE) { + intResult = 0; + warning(warningContext(), RError.Message.NA_INTRODUCED_COERCION_INT); + } else { + intResult = RRuntime.complex2rawIntValue(operand); + if (operand.getImaginaryPart() != 0) { + warning(warningContext(), RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); + } + } } return checkOutOfRange((int) operand.getRealPart(), intResult); } @@ -144,12 +171,17 @@ public abstract class CastRawNode extends CastBaseNode { } else { intValue = RRuntime.string2intNoCheck(operand); if (RRuntime.isNA(intValue)) { - warning(RError.Message.NA_INTRODUCED_COERCION); + try { + Double.parseDouble(operand); + warning(warningContext(), RError.Message.NA_INTRODUCED_COERCION_INT); + } catch (NumberFormatException e) { + warning(warningContext(), RError.Message.NA_INTRODUCED_COERCION); + } } } int intRawValue = RRuntime.int2rawIntValue(intValue); if (intRawValue != intValue) { - warning(RError.Message.OUT_OF_RANGE); + warning(warningContext(), RError.Message.OUT_OF_RANGE); return RRaw.valueOf((byte) 0); } return RRaw.valueOf((byte) intRawValue); @@ -163,134 +195,25 @@ public abstract class CastRawNode extends CastBaseNode { return ret; } - @Specialization - protected RRawVector doIntVector(RAbstractIntVector operand) { - int length = operand.getLength(); - byte[] bdata = new byte[length]; - boolean warning = false; - for (int i = 0; i < length; i++) { - int intValue = operand.getDataAt(i); - int intRawValue = RRuntime.int2rawIntValue(intValue); - if (intRawValue != intValue) { - warningBranch.enter(); - warning = true; - intRawValue = 0; - } - bdata[i] = (byte) intRawValue; - } - if (warning) { - warning(RError.Message.OUT_OF_RANGE); - } - return vectorCopy(operand, bdata); - } - - @Specialization - protected RRawVector doLogicalVector(RAbstractLogicalVector operand) { - byte[] bdata = new byte[operand.getLength()]; - boolean warning = false; - for (int i = 0; i < operand.getLength(); i++) { - int intVal = RRuntime.logical2int(operand.getDataAt(i)); - int intRawValue = RRuntime.int2rawIntValue(intVal); - if (intVal != intRawValue) { - warningBranch.enter(); - warning = true; - intRawValue = 0; - } - bdata[i] = (byte) intRawValue; - } - if (warning) { - warning(RError.Message.OUT_OF_RANGE); - } - return vectorCopy(operand, bdata); - } - - @Specialization - protected RRawVector doStringVector(RAbstractStringVector operand, - @Cached("createBinaryProfile()") ConditionProfile emptyStringProfile, - @Cached("create()") NAProfile naProfile) { - naCheck.enable(operand); + private RRawVector createResultVector(RAbstractVector operand, VectorAccess uAccess) { byte[] bdata = new byte[operand.getLength()]; - - boolean naCoercionWarning = false; - boolean outOfRangeWarning = false; - for (int i = 0; i < operand.getLength(); i++) { - String value = operand.getDataAt(i); - int intValue; - if (naCheck.check(value) || emptyStringProfile.profile(value.isEmpty())) { - intValue = RRuntime.INT_NA; - } else { - intValue = RRuntime.string2intNoCheck(value); - if (naProfile.isNA(intValue)) { - if (!value.isEmpty()) { - warningBranch.enter(); - naCoercionWarning = true; - } - } - int intRawValue = RRuntime.int2rawIntValue(intValue); - if (intValue != intRawValue) { - warningBranch.enter(); - outOfRangeWarning = true; - intValue = 0; - } + try (SequentialIterator sIter = uAccess.access(operand, warningContext())) { + while (uAccess.next(sIter)) { + bdata[sIter.getIndex()] = uAccess.getRaw(sIter); } - bdata[i] = (byte) intValue; - } - if (naCoercionWarning) { - warning(RError.Message.NA_INTRODUCED_COERCION); - } - if (outOfRangeWarning) { - warning(RError.Message.OUT_OF_RANGE); } return vectorCopy(operand, bdata); } - @Specialization - protected RRawVector doComplexVector(RAbstractComplexVector operand) { - byte[] bdata = new byte[operand.getLength()]; - boolean imaginaryDiscardedWarning = false; - boolean outOfRangeWarning = false; - for (int i = 0; i < operand.getLength(); i++) { - RComplex complexVal = operand.getDataAt(i); - int intRawValue = RRuntime.complex2rawIntValue(complexVal); - if (complexVal.getImaginaryPart() != 0.0) { - warningBranch.enter(); - imaginaryDiscardedWarning = true; - } - if ((int) complexVal.getRealPart() != intRawValue) { - warningBranch.enter(); - outOfRangeWarning = true; - intRawValue = 0; - } - bdata[i] = (byte) intRawValue; - } - if (imaginaryDiscardedWarning) { - warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); - } - if (outOfRangeWarning) { - warning(RError.Message.OUT_OF_RANGE); - } - return vectorCopy(operand, bdata); + @Specialization(guards = {"uAccess.supports(operand)", "!isRawVector(operand)"}, limit = "getGenericVectorAccessCacheSize()") + protected RRawVector doAbstractVector(RAbstractAtomicVector operand, + @Cached("operand.access()") VectorAccess uAccess) { + return createResultVector(operand, uAccess); } - @Specialization - protected RRawVector doDoubleVector(RAbstractDoubleVector operand) { - int length = operand.getLength(); - byte[] bdata = new byte[length]; - boolean warning = false; - for (int i = 0; i < length; i++) { - double doubleValue = operand.getDataAt(i); - int intRawValue = RRuntime.double2rawIntValue(doubleValue); - if (intRawValue != (int) doubleValue) { - warningBranch.enter(); - warning = true; - intRawValue = 0; - } - bdata[i] = (byte) intRawValue; - } - if (warning) { - warning(RError.Message.OUT_OF_RANGE); - } - return vectorCopy(operand, bdata); + @Specialization(replaces = "doAbstractVector", guards = {"!isRawVector(operand)"}) + protected RRawVector doAbstractVectorGeneric(RAbstractAtomicVector operand) { + return createResultVector(operand, operand.slowPathAccess()); } @Specialization @@ -298,23 +221,50 @@ public abstract class CastRawNode extends CastBaseNode { return operand; } - @Specialization - protected RRawVector doList(RAbstractListVector value) { - int length = value.getLength(); - byte[] data = new byte[length]; - for (int i = 0; i < length; i++) { - data[i] = ((RRaw) castRawRecursive(value.getDataAt(i))).getValue(); + @Specialization(guards = {"uAccess.supports(value)"}, limit = "getVectorAccessCacheSize()") + protected RRawVector doList(RAbstractListVector value, + @Cached("value.access()") VectorAccess uAccess) { + byte[] bdata = new byte[value.getLength()]; + try (SequentialIterator sIter = uAccess.access(value, warningContext())) { + while (uAccess.next(sIter)) { + int i = sIter.getIndex(); + Object entry = uAccess.getListElement(sIter); + if (entry instanceof RList) { + bdata[i] = 0; + } else { + Object castEntry = castRawRecursive(entry); + if (castEntry instanceof RRaw) { + bdata[i] = ((RRaw) castRawRecursive(castEntry)).getValue(); + } else if (castEntry instanceof RAbstractRawVector) { + RAbstractRawVector rawVector = (RAbstractRawVector) castEntry; + if (rawVector.getLength() == 1) { + bdata[i] = rawVector.getRawDataAt(0); + } else if (rawVector.getLength() == 0) { + bdata[i] = 0; + } else { + throw throwCannotCoerceListError("object"); + } + } else { + throw throwCannotCoerceListError("object"); + } + } + } } - RRawVector result = factory().createRawVector(data, getPreservedDimensions(value), getPreservedNames(value), null); + RRawVector result = factory().createRawVector(bdata, getPreservedDimensions(value), getPreservedNames(value), null); if (preserveRegAttributes()) { result.copyRegAttributesFrom(value); } return result; } + @Specialization(replaces = "doList") + protected RRawVector doListGenric(RAbstractListVector value) { + return doList(value, value.slowPathAccess()); + } + @Specialization(guards = "!pairList.isLanguage()") protected RRawVector doPairList(RPairList pairList) { - return doList(pairList.toRList()); + return (RRawVector) castRawRecursive(pairList.toRList()); } public static CastRawNode createForRFFI(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { @@ -324,4 +274,9 @@ public abstract class CastRawNode extends CastBaseNode { public static CastRawNode createNonPreserving() { return CastRawNodeGen.create(false, false, false); } + + protected boolean isRawVector(RAbstractAtomicVector x) { + return x instanceof RAbstractRawVector; + } + } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/FastPathVectorAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/FastPathVectorAccess.java index cae6a747e75e43c1adce82cb6f564649854b95bf..f7d15ce1285143d4a3fca5d2d696811ec2c63274 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/FastPathVectorAccess.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/FastPathVectorAccess.java @@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime.data.nodes; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; @@ -34,6 +35,7 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.ops.na.NAProfile; /** * Base classes for {@link VectorAccess} implementations that are used on the fast path. For @@ -443,17 +445,28 @@ public abstract class FastPathVectorAccess extends VectorAccess { @Override protected final byte getRawImpl(AccessIterator accessIter, int index) { - double value = getComplexRImpl(accessIter, index); - if (Double.isNaN(value) || value < 0 || value >= 256) { + RComplex value = getComplexImpl(accessIter, index); + + double realPart = value.getRealPart(); + double realResult = realPart; + + if (realPart > Integer.MAX_VALUE || realPart <= Integer.MIN_VALUE) { warningReportedProfile.enter(); - accessIter.warning(Message.OUT_OF_RANGE); - return 0; + accessIter.warning(RError.Message.NA_INTRODUCED_COERCION_INT); + realResult = 0; } + if (getComplexIImpl(accessIter, index) != 0) { warningReportedProfile.enter(); accessIter.warning(Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); } - return (byte) value; + + if (Double.isNaN(realPart) || realPart < 0 || realPart >= 256) { + warningReportedProfile.enter(); + accessIter.warning(Message.OUT_OF_RANGE); + realResult = 0; + } + return (byte) RRuntime.double2rawIntValue(realResult); } @Override @@ -497,6 +510,7 @@ public abstract class FastPathVectorAccess extends VectorAccess { public abstract static class FastPathFromStringAccess extends FastPathVectorAccess { ConditionProfile emptyStringProfile = ConditionProfile.createBinaryProfile(); + private NAProfile naProfile = NAProfile.create(); public FastPathFromStringAccess(Object value) { super(value); @@ -526,13 +540,48 @@ public abstract class FastPathVectorAccess extends VectorAccess { @Override protected final double getDoubleImpl(AccessIterator accessIter, int index) { - return na.convertStringToDouble(getStringImpl(accessIter, index)); + String str = getStringImpl(accessIter, index); + if (na.check(str) || emptyStringProfile.profile(str.isEmpty())) { + na.enable(true); + return RRuntime.DOUBLE_NA; + } + double value = na.convertStringToDouble(str); + if (RRuntime.isNA(value)) { + na.enable(true); + warningReportedProfile.enter(); + accessIter.warning(Message.NA_INTRODUCED_COERCION); + return RRuntime.DOUBLE_NA; + } + return value; } @Override protected final byte getRawImpl(AccessIterator accessIter, int index) { - int value = na.convertStringToInt(getStringImpl(accessIter, index)); - return value >= 0 && value <= 255 ? (byte) value : 0; + String value = getStringImpl(accessIter, index); + int intValue; + if (na.check(value) || emptyStringProfile.profile(value.isEmpty())) { + intValue = RRuntime.INT_NA; + } else { + intValue = RRuntime.string2intNoCheck(value); + if (naProfile.isNA(intValue)) { + if (!value.isEmpty()) { + warningReportedProfile.enter(); + try { + Double.parseDouble(value); + accessIter.warning(RError.Message.NA_INTRODUCED_COERCION_INT); + } catch (NumberFormatException e) { + accessIter.warning(RError.Message.NA_INTRODUCED_COERCION); + } + } + } + int intRawValue = RRuntime.int2rawIntValue(intValue); + if (intValue != intRawValue) { + warningReportedProfile.enter(); + accessIter.warning(Message.OUT_OF_RANGE); + intValue = 0; + } + } + return intValue >= 0 && intValue <= 255 ? (byte) intValue : 0; } @Override diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/SlowPathVectorAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/SlowPathVectorAccess.java index 0c6c1a9611df82c707fd3a115c0f83b1136cf0d6..92b904a098d2e17563051253118eb9e034133e4d 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/SlowPathVectorAccess.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/SlowPathVectorAccess.java @@ -70,9 +70,8 @@ public abstract class SlowPathVectorAccess extends VectorAccess { int value = getIntImpl(accessIter, index); byte result = (byte) value; if ((result & 0xff) != value) { - if (accessIter.warning(Message.OUT_OF_RANGE)) { - warningReportedProfile.enter(); - } + warningReportedProfile.enter(); + accessIter.warning(Message.OUT_OF_RANGE); return 0; } return result; @@ -150,9 +149,8 @@ public abstract class SlowPathVectorAccess extends VectorAccess { } if (value > Integer.MAX_VALUE || value <= Integer.MIN_VALUE) { na.enable(true); - if (accessIter.warning(Message.NA_INTRODUCED_COERCION_INT)) { - warningReportedProfile.enter(); - } + warningReportedProfile.enter(); + accessIter.warning(Message.NA_INTRODUCED_COERCION_INT); return RRuntime.INT_NA; } return (int) value; @@ -163,9 +161,8 @@ public abstract class SlowPathVectorAccess extends VectorAccess { int value = (int) getDoubleImpl(accessIter, index); byte result = (byte) value; if ((result & 0xff) != value) { - if (accessIter.warning(Message.OUT_OF_RANGE)) { - warningReportedProfile.enter(); - } + warningReportedProfile.enter(); + accessIter.warning(Message.OUT_OF_RANGE); return 0; } return result; @@ -250,9 +247,8 @@ public abstract class SlowPathVectorAccess extends VectorAccess { protected final byte getRawImpl(AccessIterator accessIter, int index) { byte value = getLogicalImpl(accessIter, index); if (na.check(value)) { - if (accessIter.warning(Message.OUT_OF_RANGE)) { - warningReportedProfile.enter(); - } + warningReportedProfile.enter(); + accessIter.warning(Message.OUT_OF_RANGE); return 0; } return value; @@ -395,15 +391,13 @@ public abstract class SlowPathVectorAccess extends VectorAccess { } if (value > Integer.MAX_VALUE || value <= Integer.MIN_VALUE) { na.enable(true); - if (accessIter.warning(Message.NA_INTRODUCED_COERCION_INT)) { - warningReportedProfile.enter(); - } + warningReportedProfile.enter(); + accessIter.warning(Message.NA_INTRODUCED_COERCION_INT); return RRuntime.INT_NA; } if (getComplexIImpl(accessIter, index) != 0) { - if (accessIter.warning(Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION)) { - warningReportedProfile.enter(); - } + warningReportedProfile.enter(); + accessIter.warning(Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); } return (int) value; } @@ -416,9 +410,8 @@ public abstract class SlowPathVectorAccess extends VectorAccess { return RRuntime.DOUBLE_NA; } if (getComplexIImpl(accessIter, index) != 0) { - if (accessIter.warning(Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION)) { - warningReportedProfile.enter(); - } + warningReportedProfile.enter(); + accessIter.warning(Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); } return value; } @@ -427,15 +420,13 @@ public abstract class SlowPathVectorAccess extends VectorAccess { protected final byte getRawImpl(AccessIterator accessIter, int index) { double value = getComplexRImpl(accessIter, index); if (Double.isNaN(value) || value < 0 || value >= 256) { - if (accessIter.warning(Message.OUT_OF_RANGE)) { - warningReportedProfile.enter(); - } + warningReportedProfile.enter(); + accessIter.warning(Message.OUT_OF_RANGE); return 0; } if (getComplexIImpl(accessIter, index) != 0) { - if (accessIter.warning(Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION)) { - warningReportedProfile.enter(); - } + warningReportedProfile.enter(); + accessIter.warning(Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); } return (byte) value; } @@ -495,9 +486,8 @@ public abstract class SlowPathVectorAccess extends VectorAccess { int value = na.convertStringToInt(str); if (RRuntime.isNA(value)) { na.enable(true); - if (accessIter.warning(Message.NA_INTRODUCED_COERCION)) { - warningReportedProfile.enter(); - } + warningReportedProfile.enter(); + accessIter.warning(Message.NA_INTRODUCED_COERCION); return RRuntime.INT_NA; } return value; @@ -505,7 +495,19 @@ public abstract class SlowPathVectorAccess extends VectorAccess { @Override protected final double getDoubleImpl(AccessIterator accessIter, int index) { - return na.convertStringToDouble(getStringImpl(accessIter, index)); + String str = getStringImpl(accessIter, index); + if (na.check(str) || str.isEmpty()) { + na.enable(true); + return RRuntime.DOUBLE_NA; + } + double value = na.convertStringToDouble(str); + if (RRuntime.isNA(value)) { + na.enable(true); + warningReportedProfile.enter(); + accessIter.warning(Message.NA_INTRODUCED_COERCION); + return RRuntime.DOUBLE_NA; + } + return value; } @Override @@ -528,6 +530,7 @@ public abstract class SlowPathVectorAccess extends VectorAccess { } else { complexValue = RRuntime.string2complexNoCheck(value); if (complexValue.isNA()) { + warningReportedProfile.enter(); na.enable(true); accessIter.warning(Message.NA_INTRODUCED_COERCION); } 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 24be500cb18fe54ba85bcbd257d418d1b1149bea..0a6b1dce988003c6e5dcf6359cbe5a521c00005e 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 @@ -6079,6 +6079,10 @@ quote(80L) #argv <- list(list(quote(quote), NA));as.call(argv[[1]]); quote(NA) +##com.oracle.truffle.r.test.builtins.TestBuiltin_ascharacter.noCopyCheck# +#if (!any(R.version$engine == "FastR")) { [1] TRUE } else { { x <- c('a', 'abc'); .fastr.identity(x) == .fastr.identity(as.character(x)); } } +Error: unexpected '[' in "if (!any(R.version$engine == "FastR")) { [" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascharacter.testAsCharacter# #{ as.character() } character(0) @@ -6462,6 +6466,10 @@ character(0) #argv <- structure(list(x = structure(c(1L, 2L, NA), .Label = c('AB', 'CD'), class = 'factor')), .Names = 'x');do.call('as.character.factor', argv) [1] "AB" "CD" NA +##com.oracle.truffle.r.test.builtins.TestBuiltin_ascomplex.noCopyCheck# +#if (!any(R.version$engine == "FastR")) { [1] TRUE } else { { x <- c(1+2i, 3.5+3i); .fastr.identity(x) == .fastr.identity(as.complex(x)); } } +Error: unexpected '[' in "if (!any(R.version$engine == "FastR")) { [" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascomplex.testAsComplex#Ignored.ImplementationError# #{ as.complex("+.1e+2-3i") } [1] 10-3i @@ -6658,12 +6666,16 @@ Time differences in mins Time differences in hours [1] 3.333333 23.250000 NA +##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.noCopyCheck# +#if (!any(R.version$engine == "FastR")) { [1] TRUE } else { { x <- c(1, 3.5); .fastr.identity(x) == .fastr.identity(as.double(x)); } } +Error: unexpected '[' in "if (!any(R.version$engine == "FastR")) { [" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble# #{ as.double("1.27") } [1] 1.27 -##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#Output.IgnoreWarningContext# -#{ as.double("TRUE") } +##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble# +#{ as.double('TRUE') } [1] NA Warning message: NAs introduced by coercion @@ -6672,7 +6684,7 @@ NAs introduced by coercion #{ as.double() } numeric(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble# #{ as.double(10+2i) } [1] 10 Warning message: @@ -6690,13 +6702,13 @@ numeric(0) #{ as.double(as.raw(1)) } [1] 1 -##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#Output.IgnoreWarningContext# -#{ as.double(c("1","hello")) } +##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble# +#{ as.double(c('1','hello')) } [1] 1 NA Warning message: NAs introduced by coercion -##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble# #{ as.double(c(3+3i, 4+4i)) } [1] 3 4 Warning message: @@ -6930,7 +6942,7 @@ numeric(0) [26] -6.364429e-03 -4.837092e-02 -7.047955e-02 3.494377e-02 -2.648308e-02 [31] 2.009015e-02 -##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testasdouble9#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testasdouble9# #argv <- list(c('-.1', ' 2.7 ', 'B'));as.double(argv[[1]]); [1] -0.1 2.7 NA Warning message: @@ -6940,6 +6952,10 @@ NAs introduced by coercion #argv <- structure(list(x = structure(16351.8259046444, units = 'days', class = 'difftime', origin = structure(0, class = c('POSIXct', 'POSIXt'), tzone = 'GMT'))), .Names = 'x');do.call('as.double.difftime', argv) [1] 16351.83 +##com.oracle.truffle.r.test.builtins.TestBuiltin_asexpression.noCopyCheck# +#if (!any(R.version$engine == "FastR")) { [1] TRUE } else { { x <- as.expression(quote(x+2)); .fastr.identity(x) == .fastr.identity(as.expression(x)); } } +Error: unexpected '[' in "if (!any(R.version$engine == "FastR")) { [" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asexpression.testAsExpression# #{ as.expression("name") } expression("name") @@ -7128,6 +7144,14 @@ numeric(0) #argv <- list(c(0.34345+233i,-0.34345+0.3334i));asinh(argv[[1]]); [1] 6.1441821+1.5693223i -0.3542312+0.3189009i +##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.noCopyCheck# +#if (!any(R.version$engine == "FastR")) { [1] TRUE } else { { x <- 1:10; .fastr.identity(x) == .fastr.identity(as.integer(x)); } } +Error: unexpected '[' in "if (!any(R.version$engine == "FastR")) { [" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.noCopyCheck# +#if (!any(R.version$engine == "FastR")) { [1] TRUE } else { { x <- c(1L, 3L); .fastr.identity(x) == .fastr.identity(as.integer(x)); } } +Error: unexpected '[' in "if (!any(R.version$engine == "FastR")) { [" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testAsInteger# #{ as.integer("") } [1] NA @@ -7262,6 +7286,12 @@ Error: (list) object cannot be coerced to type 'integer' #{ as.integer.cls <- function(x) 42; as.integer(structure(c(1,2), class='cls')); } [1] 42 +##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testAsInteger#Output.IgnoreWarningContext# +#{ f <- function() as.integer(10+2i); f() } +[1] 10 +Warning message: +In f() : imaginary parts discarded in coercion + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testAsInteger# #{ x<-c(a=1.1, b=2.2); dim(x)<-c(1,2); attr(x, "foo")<-"foo"; y<-as.integer(x); attributes(y) } NULL @@ -7384,6 +7414,10 @@ integer(0) #argv <- list('-1');as.integer(argv[[1]]); [1] -1 +##com.oracle.truffle.r.test.builtins.TestBuiltin_aslist.noCopyCheck# +#if (!any(R.version$engine == "FastR")) { [1] TRUE } else { { x <- list(1, 'abc', list(32)); .fastr.identity(x) == .fastr.identity(as.list(x)); } } +Error: unexpected '[' in "if (!any(R.version$engine == "FastR")) { [" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_aslist.testaslist1# #argv <- structure(list(x = structure(c(9.83610941897737, 1.76740501065812, 3.23822416444495, -2.66666666666667, -10, 28), .Names = c('X', 'Y', 'Z', 'a', 'b', 'c'))), .Names = 'x');do.call('as.list', argv) $X @@ -7405,6 +7439,10 @@ $c [1] 28 +##com.oracle.truffle.r.test.builtins.TestBuiltin_aslogical.noCopyCheck# +#if (!any(R.version$engine == "FastR")) { [1] TRUE } else { { x <- c(T, F, T, T); .fastr.identity(x) == .fastr.identity(as.logical(x)); } } +Error: unexpected '[' in "if (!any(R.version$engine == "FastR")) { [" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_aslogical.testAsLogical# #{ as.logical("TRUE") } [1] TRUE @@ -7783,30 +7821,45 @@ C:D 9 [241] "361" "362" "363" "364" "365" "366" "367" "370" "371" "372" "373" "374" [253] "375" "376" "377" -##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningContext# -#{ as.raw("test") } +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.noCopyCheck# +#if (!any(R.version$engine == "FastR")) { [1] TRUE } else { { x <- as.raw(c(1, 3)); .fastr.identity(x) == .fastr.identity(as.raw(x)); } } +Error: unexpected '[' in "if (!any(R.version$engine == "FastR")) { [" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw('1') } +[1] 01 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw('1000') } +[1] 00 +Warning message: +out-of-range values treated as 0 in coercion to raw + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWhitespace# +#{ as.raw('10000000000000000') } [1] 00 Warning messages: -1: NAs introduced by coercion +1: NAs introduced by coercion to integer range 2: out-of-range values treated as 0 in coercion to raw -##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningContext# -#{ as.raw('10000001') } +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWhitespace# +#{ as.raw('test') } [1] 00 -Warning message: -out-of-range values treated as 0 in coercion to raw +Warning messages: +1: NAs introduced by coercion +2: out-of-range values treated as 0 in coercion to raw ##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# #{ as.raw() } Error in as.raw() : 0 arguments passed to 'as.raw' which requires 1 -##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# #{ as.raw(-1) } [1] 00 Warning message: out-of-range values treated as 0 in coercion to raw -##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# #{ as.raw(-1L) } [1] 00 Warning message: @@ -7816,7 +7869,7 @@ out-of-range values treated as 0 in coercion to raw #{ as.raw(1) } [1] 01 -##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# #{ as.raw(1+1i) } [1] 01 Warning message: @@ -7826,26 +7879,125 @@ imaginary parts discarded in coercion #{ as.raw(1.1) } [1] 01 +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(1000) } +[1] 00 +Warning message: +out-of-range values treated as 0 in coercion to raw + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWhitespace# +#{ as.raw(1000+1i) } +[1] 00 +Warning messages: +1: imaginary parts discarded in coercion +2: out-of-range values treated as 0 in coercion to raw + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWhitespace# +#{ as.raw(10000000000000000) } +[1] 00 +Warning messages: +1: NAs introduced by coercion to integer range +2: out-of-range values treated as 0 in coercion to raw + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWhitespace# +#{ as.raw(10000000000000000+1i) } +[1] 00 +Warning messages: +1: NAs introduced by coercion to integer range +2: out-of-range values treated as 0 in coercion to raw + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(1000L) } +[1] 00 +Warning message: +out-of-range values treated as 0 in coercion to raw + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# #{ as.raw(1L) } [1] 01 -##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# #{ as.raw(NA) } [1] 00 Warning message: out-of-range values treated as 0 in coercion to raw +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(NA_complex_) } +[1] 00 +Warning message: +out-of-range values treated as 0 in coercion to raw + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(NA_integer_) } +[1] 00 +Warning message: +out-of-range values treated as 0 in coercion to raw + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# #{ as.raw(NULL) } raw(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningContext# -#{ as.raw(c('10000001', '42')) } -[1] 00 2a +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(TRUE) } +[1] 01 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(as.raw(list(1, 1+1i)) } +Error: unexpected '}' in "{ as.raw(as.raw(list(1, 1+1i)) }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(as.raw(list(1, 10000000000000)) } +Error: unexpected '}' in "{ as.raw(as.raw(list(1, 10000000000000)) }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(as.raw(list(1, 10000000000000, 1+1i)) } +Error: unexpected '}' in "{ as.raw(as.raw(list(1, 10000000000000, 1+1i)) }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(as.raw(list(1, 2, c(1, 2, 3))) } +Error: unexpected '}' in "{ as.raw(as.raw(list(1, 2, c(1, 2, 3))) }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(as.raw(list(1, 2, new.env())) } +Error: unexpected '}' in "{ as.raw(as.raw(list(1, 2, new.env())) }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(as.raw(list(1, NA)) } +Error: unexpected '}' in "{ as.raw(as.raw(list(1, NA)) }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(as.raw(list(1, NA, list(1))) } +Error: unexpected '}' in "{ as.raw(as.raw(list(1, NA, list(1))) }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(as.raw(list(1, NA, list(1, 2, 3))) } +Error: unexpected '}' in "{ as.raw(as.raw(list(1, NA, list(1, 2, 3))) }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(c('1', '1000')) } +[1] 01 00 Warning message: out-of-range values treated as 0 in coercion to raw +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(c('1', '2')) } +[1] 01 02 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWhitespace# +#{ as.raw(c('10000000000000000', '1')) } +[1] 00 01 +Warning messages: +1: NAs introduced by coercion to integer range +2: out-of-range values treated as 0 in coercion to raw + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWhitespace# +#{ as.raw(c('10000000000000000', '1000')) } +[1] 00 00 +Warning messages: +1: NAs introduced by coercion to integer range +2: out-of-range values treated as 0 in coercion to raw + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningContext# #{ as.raw(c(1+3i, -2-1i, NA)) } [1] 01 00 00 @@ -7853,7 +8005,7 @@ Warning messages: 1: imaginary parts discarded in coercion 2: out-of-range values treated as 0 in coercion to raw -##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# #{ as.raw(c(1, -2, 3)) } [1] 01 00 03 Warning message: @@ -7863,19 +8015,49 @@ out-of-range values treated as 0 in coercion to raw #{ as.raw(c(1, 2, 3)) } [1] 01 02 03 -##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# #{ as.raw(c(1,1000,NA)) } [1] 01 00 00 Warning message: out-of-range values treated as 0 in coercion to raw -##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningMessage# +#{ as.raw(c(1000, 1+1i)) } +[1] 00 01 +Warning messages: +1: imaginary parts discarded in coercion +2: out-of-range values treated as 0 in coercion to raw + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWhitespace# +#{ as.raw(c(10000000000000000+1i, 1+1i)) } +[1] 00 01 +Warning messages: +1: NAs introduced by coercion to integer range +2: imaginary parts discarded in coercion +3: out-of-range values treated as 0 in coercion to raw + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWhitespace# +#{ as.raw(c(10000000000000000+1i, 1000+1i, NA_complex_, 1+1i)) } +[1] 00 00 00 01 +Warning messages: +1: NAs introduced by coercion to integer range +2: imaginary parts discarded in coercion +3: out-of-range values treated as 0 in coercion to raw + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningMessage# +#{ as.raw(c(1000L, 1+1i)) } +[1] 00 01 +Warning messages: +1: imaginary parts discarded in coercion +2: out-of-range values treated as 0 in coercion to raw + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# #{ as.raw(c(1L, -2L, 3L)) } [1] 01 00 03 Warning message: out-of-range values treated as 0 in coercion to raw -##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# #{ as.raw(c(1L, -2L, NA)) } [1] 01 00 00 Warning message: @@ -7885,6 +8067,23 @@ out-of-range values treated as 0 in coercion to raw #{ as.raw(c(1L, 2L, 3L)) } [1] 01 02 03 +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(c(1L, 2L, NA_integer_)) } +[1] 01 02 00 +Warning message: +out-of-range values treated as 0 in coercion to raw + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWhitespace# +#{ as.raw(c(NA_complex_, 1+1i)) } +[1] 00 01 +Warning messages: +1: imaginary parts discarded in coercion +2: out-of-range values treated as 0 in coercion to raw + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw(c(TRUE, FALSE)) } +[1] 01 00 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# #{ as.raw(list("1", 2L, 3.4)) } [1] 01 02 03 @@ -81971,7 +82170,7 @@ Error in call(f, quote(A)) : first argument must be a character string #{ as.complex(as.character(c(1+1i,1+1i))) } [1] 1+1i 1+1i -##com.oracle.truffle.r.test.builtins.TestMiscBuiltins.testCasts#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestMiscBuiltins.testCasts# #{ as.complex(as.double(c(1+1i,1+1i))) } [1] 1+0i 1+0i Warning message: @@ -81987,7 +82186,7 @@ imaginary parts discarded in coercion #{ as.complex(as.logical(c(1+1i,1+1i))) } [1] 1+0i 1+0i -##com.oracle.truffle.r.test.builtins.TestMiscBuiltins.testCasts#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestMiscBuiltins.testCasts# #{ as.complex(as.raw(c(1+1i,1+1i))) } [1] 1+0i 1+0i Warning message: @@ -145078,13 +145277,13 @@ NAs introduced by coercion #if (!any(R.version$engine == "FastR")) { as.complex(c(TRUE,FALSE,TRUE)) } else { to <- .fastr.interop.new(java.type('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$listBoolean); } [1] 1+0i 0+0i 1+0i -##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage# +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX# #if (!any(R.version$engine == "FastR")) { as.double("a string") } else { to <- .fastr.interop.new(java.type('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStaticStringObject) } [1] NA Warning message: NAs introduced by coercion -##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage# +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX# #if (!any(R.version$engine == "FastR")) { as.double("a") } else { to <- .fastr.interop.new(java.type('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStaticCharObject) } [1] NA Warning message: @@ -145671,13 +145870,13 @@ Warning messages: #if (!any(R.version$engine == "FastR")) { as.raw(127) } else { to <- .fastr.interop.new(java.type('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStaticByteObject) } [1] 7f -##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage# +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX# #if (!any(R.version$engine == "FastR")) { as.raw(2147483647) } else { to <- .fastr.interop.new(java.type('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStaticIntegerObject) } [1] 00 Warning message: out-of-range values treated as 0 in coercion to raw -##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage# +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX# #if (!any(R.version$engine == "FastR")) { as.raw(32767) } else { to <- .fastr.interop.new(java.type('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStaticShortObject) } [1] 00 Warning message: diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java index 6e399a441abd6d4f46051720d2ed0de86bbe484e..4f5d29c038e4e7362ca58732176868733e161776 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java @@ -281,4 +281,9 @@ public class TestBuiltin_ascharacter extends TestBase { assertEval("{ as.character.cls <- function(x) 42; as.character(structure(c(1,2), class='cls')); }"); assertEval("{ y <- c('a', 'b'); attr(y, 'someAttr') <- 'someValue'; x <- as.character(y); x[[1]] <- '42'; y }"); } + + @Test + public void noCopyCheck() { + assertEvalFastR("{ x <- c('a', 'abc'); .fastr.identity(x) == .fastr.identity(as.character(x)); }", "[1] TRUE"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java index 17871c3a901121188d634a07c72ede6fec287ddf..ec38db8e732b7e20430b0cb062695dc58fa466b3 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java @@ -116,4 +116,9 @@ public class TestBuiltin_ascomplex extends TestBase { assertEval(Output.IgnoreWarningContext, "{ as.complex(list(\"foo\")) }"); assertEval("{ as.complex.cls <- function(x) 42; as.complex(structure(c(1,2), class='cls')); }"); } + + @Test + public void noCopyCheck() { + assertEvalFastR("{ x <- c(1+2i, 3.5+3i); .fastr.identity(x) == .fastr.identity(as.complex(x)); }", "[1] TRUE"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java index 4e7a8fd0cc6cb914133986bbc05578bdc41c50d1..c17644bebbfbcffe8fad88f394fc78770b5f09c1 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java @@ -69,7 +69,7 @@ public class TestBuiltin_asdouble extends TestBase { @Test public void testasdouble9() { - assertEval(Output.IgnoreWarningContext, "argv <- list(c('-.1', ' 2.7 ', 'B'));as.double(argv[[1]]);"); + assertEval("argv <- list(c('-.1', ' 2.7 ', 'B'));as.double(argv[[1]]);"); } @Test @@ -188,14 +188,19 @@ public class TestBuiltin_asdouble extends TestBase { assertEval("{ as.double(\"1.27\") }"); assertEval("{ as.double(1L) }"); assertEval("{ as.double(as.raw(1)) }"); - assertEval(Output.IgnoreWarningContext, "{ as.double(c(\"1\",\"hello\")) }"); - assertEval(Output.IgnoreWarningContext, "{ as.double(\"TRUE\") }"); - assertEval(Output.IgnoreWarningContext, "{ as.double(10+2i) }"); - assertEval(Output.IgnoreWarningContext, "{ as.double(c(3+3i, 4+4i)) }"); + assertEval("{ as.double(c('1','hello')) }"); + assertEval("{ as.double('TRUE') }"); + assertEval("{ as.double(10+2i) }"); + assertEval("{ as.double(c(3+3i, 4+4i)) }"); assertEval("{ x<-c(a=1.1, b=2.2); dim(x)<-c(1,2); attr(x, \"foo\")<-\"foo\"; y<-as.double(x); attributes(y) }"); assertEval("{ x<-c(a=1L, b=2L); dim(x)<-c(1,2); attr(x, \"foo\")<-\"foo\"; y<-as.double(x); attributes(y) }"); assertEval("{ as.double(NULL) }"); assertEval("{ as.double.cls <- function(x) 42; as.double(structure(c(1,2), class='cls')); }"); assertEval("{ y <- c(3.1, 3.2); attr(y, 'someAttr') <- 'someValue'; x <- as.double(y); x[[1]] <- 42; y }"); } + + @Test + public void noCopyCheck() { + assertEvalFastR("{ x <- c(1, 3.5); .fastr.identity(x) == .fastr.identity(as.double(x)); }", "[1] TRUE"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asexpression.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asexpression.java index ac10247fbe5be7a0a41cb806567857f810cb7a8d..f105859b422f4481da0edad905b916bd80a244f0 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asexpression.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asexpression.java @@ -45,4 +45,9 @@ public class TestBuiltin_asexpression extends TestBase { assertEval(Output.IgnoreErrorContext, "{ as.expression(sum) }"); assertEval(Output.IgnoreErrorContext, "{ as.expression(function() {}) }"); } + + @Test + public void noCopyCheck() { + assertEvalFastR("{ x <- as.expression(quote(x+2)); .fastr.identity(x) == .fastr.identity(as.expression(x)); }", "[1] TRUE"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java index dff1e558d942c4ac14007c559e22f05eed1201b8..b4a10d805407ed648820074951978e381ca909b5 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java @@ -138,6 +138,7 @@ public class TestBuiltin_asinteger extends TestBase { assertEval("{ as.integer(-0/0) }"); assertEval("{ as.integer(as.raw(c(1,2,3,4))) }"); assertEval("{ as.integer(10+2i) }"); + assertEval(Output.IgnoreWarningContext, "{ f <- function() as.integer(10+2i); f() }"); assertEval("{ as.integer(c(3+3i, 4+4i)) }"); assertEval("{ as.integer(10000000000000) }"); assertEval("{ as.integer(list(c(1),2,3)) }"); @@ -162,4 +163,10 @@ public class TestBuiltin_asinteger extends TestBase { assertEval("{ as.integer(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA)) }"); assertEval("{ y <- c(3L, 4L); attr(y, 'someAttr') <- 'someValue'; x <- as.integer(y); x[[1]] <- 42L; y }"); } + + @Test + public void noCopyCheck() { + assertEvalFastR("{ x <- c(1L, 3L); .fastr.identity(x) == .fastr.identity(as.integer(x)); }", "[1] TRUE"); + assertEvalFastR("{ x <- 1:10; .fastr.identity(x) == .fastr.identity(as.integer(x)); }", "[1] TRUE"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aslist.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aslist.java index d722f781e1613f5f065cae918de7e94184385138..a758d09f06a8d5a26b674e993c902e97f31ea9d2 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aslist.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aslist.java @@ -33,4 +33,9 @@ public class TestBuiltin_aslist extends TestBase { assertEval("argv <- structure(list(x = structure(c(9.83610941897737, 1.76740501065812, 3.23822416444495, -2.66666666666667, -10, 28), .Names = c('X', 'Y', 'Z', 'a', 'b', 'c'))), .Names = 'x');" + "do.call('as.list', argv)"); } + + @Test + public void noCopyCheck() { + assertEvalFastR("{ x <- list(1, 'abc', list(32)); .fastr.identity(x) == .fastr.identity(as.list(x)); }", "[1] TRUE"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aslogical.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aslogical.java index f29842171b408c5c981402cb5a6fb98280f51150..9928a518fbfa5c55ddd698f799339fd4fc91b31c 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aslogical.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aslogical.java @@ -112,4 +112,9 @@ public class TestBuiltin_aslogical extends TestBase { assertEval("{ as.logical.cls <- function(x) 42; as.logical(structure(c(1,2), class='cls')); }"); assertEval("{ y <- c(T, F); attr(y, 'someAttr') <- 'someValue'; x <- as.logical(y); x[[1]] <- F; y }"); } + + @Test + public void noCopyCheck() { + assertEvalFastR("{ x <- c(T, F, T, T); .fastr.identity(x) == .fastr.identity(as.logical(x)); }", "[1] TRUE"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java index af160b0108a973cc3eb43f1e2e43d14fd7239c22..cb6347db0484d5e96597acbebf38f2e5ce37dca4 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java @@ -63,25 +63,60 @@ public class TestBuiltin_asraw extends TestBase { assertEval("{ as.raw(NULL) }"); assertEval("{ as.raw(1) }"); assertEval("{ as.raw(1L) }"); + assertEval("{ as.raw(TRUE) }"); + assertEval("{ as.raw(c(TRUE, FALSE)) }"); + assertEval("{ as.raw(NA_integer_) }"); assertEval("{ as.raw(1.1) }"); assertEval("{ as.raw(c(1, 2, 3)) }"); assertEval("{ as.raw(c(1L, 2L, 3L)) }"); + assertEval("{ as.raw(c(1L, 2L, NA_integer_)) }"); assertEval("{ as.raw(list(1,2,3)) }"); assertEval("{ as.raw(list(\"1\", 2L, 3.4)) }"); + assertEval("{ as.raw(as.raw(list(1, 2, c(1, 2, 3))) }"); + assertEval("{ as.raw(as.raw(list(1, 2, new.env())) }"); + assertEval("{ as.raw(as.raw(list(1, 10000000000000)) }"); + assertEval("{ as.raw(as.raw(list(1, 1+1i)) }"); + assertEval("{ as.raw(as.raw(list(1, 10000000000000, 1+1i)) }"); + assertEval("{ as.raw(as.raw(list(1, NA)) }"); + assertEval("{ as.raw(as.raw(list(1, NA, list(1))) }"); + assertEval("{ as.raw(as.raw(list(1, NA, list(1, 2, 3))) }"); assertEval("{ as.raw.cls <- function(x) 42; as.raw(structure(c(1,2), class='cls')); }"); - assertEval(Output.IgnoreWarningContext, "{ as.raw(1+1i) }"); - assertEval(Output.IgnoreWarningContext, "{ as.raw(-1) }"); - assertEval(Output.IgnoreWarningContext, "{ as.raw(-1L) }"); - assertEval(Output.IgnoreWarningContext, "{ as.raw(NA) }"); - assertEval(Output.IgnoreWarningContext, "{ as.raw(\"test\") }"); + assertEval("{ as.raw(1+1i) }"); + assertEval("{ as.raw(-1) }"); + assertEval("{ as.raw(-1L) }"); + assertEval("{ as.raw(NA) }"); + assertEval("{ as.raw(1000L) }"); + assertEval("{ as.raw(1000) }"); + assertEval(Output.IgnoreWhitespace, "{ as.raw(10000000000000000) }"); + assertEval(Output.IgnoreWhitespace, "{ as.raw('test') }"); + assertEval("{ as.raw('1') }"); + assertEval("{ as.raw('1000') }"); + assertEval(Output.IgnoreWhitespace, "{ as.raw('10000000000000000') }"); + assertEval("{ as.raw(c('1', '2')) }"); + assertEval("{ as.raw(c('1', '1000')) }"); + assertEval(Output.IgnoreWhitespace, "{ as.raw(c('10000000000000000', '1000')) }"); + assertEval(Output.IgnoreWhitespace, "{ as.raw(c('10000000000000000', '1')) }"); assertEval(Output.IgnoreWarningContext, "{ as.raw(c(1+3i, -2-1i, NA)) }"); - assertEval(Output.IgnoreWarningContext, "{ as.raw(c(1, -2, 3)) }"); - assertEval(Output.IgnoreWarningContext, "{ as.raw(c(1,1000,NA)) }"); - assertEval(Output.IgnoreWarningContext, "{ as.raw(c(1L, -2L, 3L)) }"); - assertEval(Output.IgnoreWarningContext, "{ as.raw(c(1L, -2L, NA)) }"); - assertEval(Output.IgnoreWarningContext, "{ as.raw('10000001') }"); - assertEval(Output.IgnoreWarningContext, "{ as.raw(c('10000001', '42')) }"); + assertEval(Output.IgnoreWhitespace, "{ as.raw(10000000000000000+1i) }"); + assertEval("{ as.raw(NA_complex_) }"); + assertEval(Output.IgnoreWhitespace, "{ as.raw(1000+1i) }"); + assertEval(Output.IgnoreWhitespace, "{ as.raw(c(10000000000000000+1i, 1+1i)) }"); + assertEval(Output.IgnoreWhitespace, "{ as.raw(c(NA_complex_, 1+1i)) }"); + // gnur has a fixed warnign order, + // no matter how they are encountered while traversing the vector + assertEval(Output.IgnoreWarningMessage, "{ as.raw(c(1000L, 1+1i)) }"); + assertEval(Output.IgnoreWarningMessage, "{ as.raw(c(1000, 1+1i)) }"); + assertEval(Output.IgnoreWhitespace, "{ as.raw(c(10000000000000000+1i, 1000+1i, NA_complex_, 1+1i)) }"); + assertEval("{ as.raw(c(1, -2, 3)) }"); + assertEval("{ as.raw(c(1,1000,NA)) }"); + assertEval("{ as.raw(c(1L, -2L, 3L)) }"); + assertEval("{ as.raw(c(1L, -2L, NA)) }"); assertEval("{ y <- as.raw(c(5L, 6L)); attr(y, 'someAttr') <- 'someValue'; x <- as.raw(y); x[[1]] <- as.raw(42); y }"); } + + @Test + public void noCopyCheck() { + assertEvalFastR("{ x <- as.raw(c(1, 3)); .fastr.identity(x) == .fastr.identity(as.raw(x)); }", "[1] TRUE"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java index 846505b5dbf4d8fc8d913bcf5dd911bd65d6f62b..53e851c99ef1a9dc771733f010e73063c70f3a9b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java @@ -109,8 +109,8 @@ public class TestMiscBuiltins extends TestBase { assertEval("{ x <- 1:3; z <- as.matrix(x); x }"); assertEval("{ x <- 1:3 ; attr(x,\"my\") <- 10 ; attributes(as.matrix(x)) }"); - assertEval(Output.IgnoreWarningContext, "{ as.complex(as.double(c(1+1i,1+1i))) }"); - assertEval(Output.IgnoreWarningContext, "{ as.complex(as.raw(c(1+1i,1+1i))) }"); + assertEval("{ as.complex(as.double(c(1+1i,1+1i))) }"); + assertEval("{ as.complex(as.raw(c(1+1i,1+1i))) }"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java index 0b61650e7f505ebb35d33f562157e55a96858bbf..0c765ee621c368083deeabf0850b649487d3586a 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java @@ -978,11 +978,11 @@ public class TestJavaInterop extends TestBase { if (name.startsWith("fieldStatic") && name.endsWith("Object")) { if (asXXX.equals("as.character") && name.contains("Long")) { assertEvalFastR(Ignored.ImplementationError, expr, getAsXXX(f.get(t), asXXX)); - } else if ((asXXX.equals("as.double") || asXXX.equals("as.raw")) && (name.contains("String") || name.contains("Char"))) { + } else if ((asXXX.equals("as.raw")) && (name.contains("String") || name.contains("Char"))) { assertEvalFastR(Output.IgnoreWarningMessage, expr, getAsXXX(f.get(t), asXXX)); } else if (asXXX.equals("as.expression") && (name.contains("Long") || name.contains("Double"))) { assertEvalFastR(Ignored.ImplementationError, expr, getAsXXX(f.get(t), asXXX)); - } else if (asXXX.equals("as.raw") && (name.contains("Short") || name.contains("Integer") || name.contains("Long") || name.contains("Double") || name.contains("NaN"))) { + } else if (asXXX.equals("as.raw") && (name.contains("Long") || name.contains("Double") || name.contains("NaN"))) { assertEvalFastR(Output.IgnoreWarningMessage, expr, getAsXXX(f.get(t), asXXX)); } else if (asXXX.equals("as.symbol") && (name.contains("Long") || name.contains("Double") || name.contains("Float"))) { assertEvalFastR(Ignored.ImplementationError, expr, getAsXXX(f.get(t), asXXX));