diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java index 201bde0fdcddb5acde4cd5a59ff7487f8cabd79b..c7ee5c887ec57907020174381d898de1ee9385be 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java @@ -29,6 +29,7 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.attributes.CopyAttributesNode; import com.oracle.truffle.r.nodes.attributes.CopyAttributesNodeGen; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; @@ -45,6 +46,7 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RString; @@ -174,7 +176,8 @@ public abstract class BinaryBooleanNode extends RBuiltinNode.Arg2 { @Specialization(guards = {"isOneList(left, right)"}) protected Object doList(VirtualFrame frame, RAbstractVector left, RAbstractVector right, @Cached("create()") CastTypeNode cast, - @Cached("createRecursive()") BinaryBooleanNode recursive) { + @Cached("createRecursive()") BinaryBooleanNode recursive, + @Cached("create()") BranchProfile listCoercionErrorBranch) { Object recursiveLeft = left; if (isRAbstractListVector(left)) { if (copyAttributes == null) { @@ -182,6 +185,10 @@ public abstract class BinaryBooleanNode extends RBuiltinNode.Arg2 { copyAttributes = insert(CopyAttributesNodeGen.create(true)); } recursiveLeft = castListToAtomic((RAbstractListBaseVector) left, cast, right.getRType(), copyAttributes); + if (recursiveLeft == null) { + listCoercionErrorBranch.enter(); + throw RError.error(RError.NO_CALLER, RError.Message.LIST_COERCION, right.getRType().getName()); + } } Object recursiveRight = right; if (isRAbstractListVector(right)) { @@ -190,6 +197,10 @@ public abstract class BinaryBooleanNode extends RBuiltinNode.Arg2 { copyAttributes = insert(CopyAttributesNodeGen.create(true)); } recursiveRight = castListToAtomic((RAbstractListBaseVector) right, cast, left.getRType(), copyAttributes); + if (recursiveRight == null) { + listCoercionErrorBranch.enter(); + throw RError.error(RError.NO_CALLER, RError.Message.LIST_COERCION, left.getRType().getName()); + } } return recursive.execute(frame, recursiveLeft, recursiveRight); } @@ -200,6 +211,9 @@ public abstract class BinaryBooleanNode extends RBuiltinNode.Arg2 { Object store = result.getInternalStore(); for (int i = 0; i < source.getLength(); i++) { Object value = source.getDataAt(i); + if (value == RNull.instance) { + return null; + } if (type == RType.Character) { if (!(value instanceof String)) { value = RDeparse.deparse(value); 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 a589460550e8f126bceaf27dbb14857b832c3410..c0d15c5eb83077efeb6892b339c0b28dbaee9538 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 @@ -43348,6 +43348,18 @@ Error in Ops.factor(factor(c("a", "b", "c")), factor(c(1, 2, 3))) : #{ c(1,2,3,4,5) %in% c(1,2,1,2) } [1] TRUE TRUE FALSE FALSE FALSE +##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testListWithNull# +#{ c(1, 1) < list(1, NULL) } +Error: (list) object cannot be coerced to type 'double' + +##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testListWithNull# +#{ list(1, NULL) < c(1, 1) } +Error: (list) object cannot be coerced to type 'double' + +##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testListWithNull# +#{ list(NULL) < 1 } +Error: (list) object cannot be coerced to type 'double' + ##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testMatMult# #{ as.vector(c(1,2,3)) %*% t(as.vector(c(1,2))) } [,1] [,2] diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java index c5b231862d5e112c830d8340c99401e6f2bbde44..26b615f6c3acf80d6ac4057e0c3500c8138d7d37 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java @@ -2079,4 +2079,11 @@ public class TestBuiltin_operators extends TestBase { assertEval("{ l <- list(an=T, bn=F, T, F); l == T }"); assertEval("{ l <- list(an=T, bn=F, T, F); T == l }"); } + + @Test + public void testListWithNull() { + assertEval("{ list(NULL) < 1 }"); + assertEval("{ list(1, NULL) < c(1, 1) }"); + assertEval("{ c(1, 1) < list(1, NULL) }"); + } }