diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/GetAttributesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/GetAttributesNode.java index 9bb878e1ecf6a293769a6c02f05f57060646b28a..ee6694464fc702ceb2be4ddfda8b7bf956e5a526 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/GetAttributesNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/GetAttributesNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -41,6 +41,9 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RList; 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.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.env.REnvironment; @@ -65,16 +68,32 @@ public abstract class GetAttributesNode extends RBaseNode { public abstract Object execute(RAttributable attributable); - @Specialization + @Specialization(guards = "!isPairList(container)") protected Object attributesNull(RAbstractContainer container, @Cached("createBinaryProfile()") ConditionProfile hasAttributesProfile) { if (hasAttributesProfile.profile(hasAttributes(container))) { - return createResult(container, container instanceof RLanguage); + return createResult(container, container instanceof RLanguage, null); } else { return RNull.instance; } } + @Specialization + @TruffleBoundary + protected Object attributesPairList(RPairList pairList) { + RStringVector names = pairList.getNames(); + if (hasAttributes(pairList)) { + return createResult(pairList, false, names); + } else if (names != null) { + return RDataFactory.createList(new Object[] {names}, RDataFactory.createStringVector(RRuntime.NAMES_ATTR_KEY)); + } + return RNull.instance; + } + + protected static boolean isPairList(RAbstractContainer x) { + return x instanceof RPairList; + } + /** * Unusual cases that it is not worth specializing on as they are not performance-centric, * basically any type that is not an {@link RAbstractContainer} but is {@link RAttributable}, @@ -84,7 +103,7 @@ public abstract class GetAttributesNode extends RBaseNode { @TruffleBoundary protected Object attributes(RAttributable object) { if (hasAttributes(object)) { - return createResult(object, false); + return createResult(object, false, null); } else { return RNull.instance; } @@ -107,12 +126,17 @@ public abstract class GetAttributesNode extends RBaseNode { /** * {@code language} objects behave differently regarding "names"; they don't get included. */ - private Object createResult(RAttributable attributable, boolean ignoreNames) { + private Object createResult(RAttributable attributable, boolean ignoreNames, RStringVector explicitNames) { DynamicObject attributes = attributable.getAttributes(); - int size = attributes.size(); + int size = attributes.size() + (explicitNames == null ? 0 : 1); String[] names = new String[size]; Object[] values = new Object[size]; int z = 0; + if (explicitNames != null) { + values[0] = explicitNames; + names[0] = RRuntime.NAMES_ATTR_KEY; + z = 1; + } for (RAttributesLayout.RAttribute attr : arrayAttrAccess.execute(attributes)) { String name = attr.getName(); if (ignoreNames && name.equals(RRuntime.NAMES_ATTR_KEY)) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java index 80a0eb023b0a2415cb4553a190aed7898e04d7c8..e3be9c96ea3e37a40fd7df240ff2bfbe95fa3640 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java @@ -326,6 +326,9 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra @Override public RStringVector getNames() { + if (this.tag == RNull.instance) { + return null; + } int l = getLength(); String[] data = new String[l]; RPairList pl = this; 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 f5d0f59a8ec2837e8e31e6e0e53dbc93c41d6dcc..c35c33503ed0cde9fac550496c9d66d2305340ba 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 @@ -10358,6 +10358,31 @@ attr(,"Object created") a b c 1 2 3 +##com.oracle.truffle.r.test.builtins.TestBuiltin_attributes.testAttributes# +#attributes(pairlist(1,2,3)) +NULL + +##com.oracle.truffle.r.test.builtins.TestBuiltin_attributes.testAttributes# +#attributes(pairlist(a=1, b=2)) +$names +[1] "a" "b" + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_attributes.testAttributes# +#attributes(structure(pairlist(1,2,3), myattr=42)) +$myattr +[1] 42 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_attributes.testAttributes# +#attributes(structure(pairlist(a=1,b=2,c=3), myattr=42)) +$names +[1] "a" "b" "c" + +$myattr +[1] 42 + + ##com.oracle.truffle.r.test.builtins.TestBuiltin_attributes.testAttributes# #{ e <- new.env(); attributes(e) <- list(a=1); attributes(e) } $a @@ -41325,6 +41350,18 @@ Error in k() : argument "y" is missing, with no default #{ x <- quote(plot(x = age, y = weight)); names(x) } [1] "" "x" "y" +##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testNames# +#names(pairlist(1,2,3)) +NULL + +##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testNames# +#names(pairlist(a=1,2,q=3)) +[1] "a" "" "q" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testNames# +#names(pairlist(a=3, b=4)) +[1] "a" "b" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testNames# #v <- parse(text="useDynLib(digest, digest_impl=digest)"); names(v[[1]][3]) [1] "digest_impl" diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributes.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributes.java index af13a6708d2465a36ad8d63b0cd1408130038d9c..d5425ad60c595995c9591d1886dfa45285e53db4 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributes.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributes.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2017, Oracle and/or its affiliates + * Copyright (c) 2013, 2018, Oracle and/or its affiliates * * All rights reserved. */ @@ -195,5 +195,10 @@ public class TestBuiltin_attributes extends TestBase { assertEval("{ e <- new.env(); attributes(e) <- list(a=1); attributes(e) }"); assertEval("{ e <- new.env(); attributes(e) <- list(class=\"srcfile\"); attributes(e) }"); + + assertEval("attributes(pairlist(a=1, b=2))"); + assertEval("attributes(pairlist(1,2,3))"); + assertEval("attributes(structure(pairlist(1,2,3), myattr=42))"); + assertEval("attributes(structure(pairlist(a=1,b=2,c=3), myattr=42))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java index 174fa47cdafbf0d9eebbf262df35e699cdd8dead..147f9137f9ae7786841967d1d25194d966a49e6a 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java @@ -208,6 +208,9 @@ public class TestBuiltin_names extends TestBase { assertEval("{ e <- new.env(); names(e) <- c('a'); }"); // FIXME: set names on language does not set the first name assertEval(Ignored.ImplementationError, "{ x <- parse(text='x+y')[[1]]; names(x) <- c('a','b','c'); names(x); }"); + assertEval("names(pairlist(a=3, b=4))"); + assertEval("names(pairlist(1,2,3))"); + assertEval("names(pairlist(a=1,2,q=3))"); } @Test