diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java index 7c312cd0e9752c17bcd3c7dad0fab5167032b72a..9c444c4d9a66f873274d46797f7d3855ba6570e5 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java @@ -31,6 +31,7 @@ import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RLogical; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; @@ -39,6 +40,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.env.REnvironment; @SuppressWarnings("unused") @RBuiltin(name = "format", kind = INTERNAL, parameterNames = {"x", "trim", "digits", "nsmall", "width", "justify", "na.encode", "scientific", "decimal.mark"}, behavior = PURE) @@ -145,6 +147,12 @@ public abstract class Format extends RBuiltinNode { return (RStringVector) valuePrinter.prettyPrint(frame, value, AnyVectorToStringVectorWriter::new); } + @Specialization + protected RStringVector format(VirtualFrame frame, REnvironment value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, + String decimalMark) { + return RDataFactory.createStringVector(value.getPrintName()); + } + @Specialization protected RStringVector format(RAbstractStringVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, String decimalMark) { // TODO: implement full semantics diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java index 591c9236aa09c56baee7ac784bced4ca724aabf2..e41593722b78fb9fbe863d0bbae378ca83e80edf 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java @@ -89,7 +89,7 @@ abstract class AccessFieldSpecial extends SpecialsUtils.ListFieldSpecialBase { @TypeSystemReference(EmptyTypeSystemFlatLayout.class) public abstract class AccessField extends RBuiltinNode { - @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.FIELD_SUBSCRIPT, true); private final ConditionProfile invalidAtomicVector = ConditionProfile.createBinaryProfile(); private final BranchProfile error = BranchProfile.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java index 8723f67b6fa6bdc153df5f69d4b2b2b66bc0fbbb..dd6ee6a107f3b4dbbe310220b0e7faafc912b12b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java @@ -38,6 +38,7 @@ import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode; +import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.opt.ShareObjectNode; import com.oracle.truffle.r.nodes.unary.CastListNode; @@ -45,6 +46,7 @@ import com.oracle.truffle.r.nodes.unary.CastListNodeGen; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.builtins.RSpecialFactory; import com.oracle.truffle.r.runtime.data.RList; @@ -118,14 +120,14 @@ abstract class UpdateFieldSpecial extends SpecialsUtils.ListFieldSpecialBase { @TypeSystemReference(EmptyTypeSystemFlatLayout.class) public abstract class UpdateField extends RBuiltinNode { - @Child private ReplaceVectorNode update = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + @Child private ReplaceVectorNode update = ReplaceVectorNode.create(ElementAccessMode.FIELD_SUBSCRIPT, true); @Child private CastListNode castList; private final ConditionProfile coerceList = ConditionProfile.createBinaryProfile(); static { Casts casts = new Casts(UpdateField.class); - casts.arg(1).defaultError(Message.INVALID_SUBSCRIPT).mustBe(stringValue()).asStringVector().findFirst(); + casts.arg(1).defaultError(Message.INVALID_SUBSCRIPT).mustBe(stringValue(), RError.NO_CALLER, Message.INVALID_SUBSCRIPT_TYPE, Predef.typeName()).asStringVector().findFirst(); } public static RNode createSpecial(ArgumentsSignature signature, RNode[] arguments, @SuppressWarnings("unused") boolean inReplacement) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java index 4a48b4c194a1d777677bf48d6762813ea6eeb7af..6e7fff3d2d83c7fd85d9fbb98b08e68f554be945 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java @@ -396,7 +396,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode { return RType.maxPrecedence(value, vector); } else if (vector.isNull() || value.isNull()) { if (!value.isNull()) { - return value; + return (mode == ElementAccessMode.FIELD_SUBSCRIPT) ? RType.List : value; } if (mode.isSubscript() && numberOfDimensions > 1) { return null; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ElementAccessMode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ElementAccessMode.java index eb7a6003aeb220c2e58650efe0dab8c4917be87d..0365dbe31ae8d30721a70d5bdf451fe166e5c7f3 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ElementAccessMode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ElementAccessMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,9 @@ public enum ElementAccessMode { /* x[[a]] */ SUBSCRIPT, + /* x$a */ + FIELD_SUBSCRIPT, + /* x[a] */ SUBSET; @@ -38,6 +41,6 @@ public enum ElementAccessMode { } public boolean isSubscript() { - return this == SUBSCRIPT; + return this == SUBSCRIPT || this == FIELD_SUBSCRIPT; } } 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 35b20f777430d5e28e068762d1fae38700a1dcb0..b9140ddfa37645ceea1f58eb135f6b32508dd29f 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 @@ -80466,6 +80466,31 @@ $z [1] 7 43 +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testNullListAssignment# +#a<- NULL; a <- `$<-`(a, "a", 1); dput(a) +structure(list(a = 1), .Names = "a") + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testNullListAssignment# +#a<- NULL; a <- `$<-`(a, 1, 1); dput(a) +Error: invalid subscript type 'double' + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testNullListAssignment# +#a<- NULL; a <- `[[<-`(a, "a", 1); dput(a) +structure(1, .Names = "a") + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testNullListAssignment# +#a<- NULL; a <- `[[<-`(a, 1, 1); dput(a) +1 + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testNullListAssignment# +#a<-NULL; a$b<-42L; dput(a) +structure(list(b = 42L), .Names = "b") + +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testNullListAssignment# +#a<-NULL; a$b<-print; dput(a) +structure(list(b = function (x, ...) +UseMethod("print")), .Names = "b") + ##com.oracle.truffle.r.test.library.base.TestSimpleLoop.testDynamic# #{ l <- quote({x <- 0 ; for(i in 1:10) { x <- x + i } ; x}) ; f <- function() { eval(l) } ; x <<- 10 ; f() } [1] 55 diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java index 8ef63beb180da0d71c6edd5735e613932e97e0b5..d783aa1d15d5436a5548a211a07b20f9e9ec8603 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -311,5 +311,6 @@ public class TestBuiltin_format extends TestBase { assertEval("{ format(c(7,42)) }"); assertEval("{ format(c(7.42,42.7)) }"); assertEval("{ format(c(7.42,42.7,NA)) }"); + assertEval("{ .Internal(format(.GlobalEnv,FALSE,NA,0,0,3,TRUE,NA,'.')) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java index cfcffb27f3dbbe436ce32644f678d54bc4fb0885..d0add2169743d95cfebce812ad9a3e8811a81da6 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -150,4 +150,15 @@ public class TestSimpleLists extends TestBase { assertEval("l <- list(); l$x <- c(NA); length(l$x) <- 10; l$x[1] <- 42; invisible(tracemem(l$x)); l$x[2:9] <- 42;"); assertEval("x <- list(c(1,2,3)); invisible(tracemem(x)); x[[1]] <- 42;"); } + + @Test + public void testNullListAssignment() { + assertEval("a<-NULL; a$b<-42L; dput(a)"); + assertEval("a<-NULL; a$b<-print; dput(a)"); + assertEval("a<- NULL; a <- `$<-`(a, \"a\", 1); dput(a)"); + assertEval("a<- NULL; a <- `[[<-`(a, \"a\", 1); dput(a)"); + assertEval("a<- NULL; a <- `[[<-`(a, 1, 1); dput(a)"); + assertEval("a<- NULL; a <- `$<-`(a, 1, 1); dput(a)"); + } + }