aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Florian Weikert <fwe@google.com>2015-12-14 12:06:10 +0000
committerGravatar Dmitry Lomov <dslomov@google.com>2015-12-15 11:59:45 +0000
commitd5e3350f3d2a89c12c87208bc41daa89f4d31405 (patch)
tree2fb72d399373c29e60a9743d5347bc124bdc7f3f /src
parent9f5a530f678b464ba59e27a439f8dc5e5304522a (diff)
Skylark: implemented reversed()
-- MOS_MIGRATED_REVID=110141376
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java41
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/EnvironmentTest.java4
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java45
3 files changed, 86 insertions, 4 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
index 3d8c7feb8c..f43f714587 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.Location;
@@ -935,6 +936,40 @@ public class MethodLibrary {
};
@SkylarkSignature(
+ name = "reversed",
+ returnType = MutableList.class,
+ doc = "Returns a list that contains the elements of the original sequence in reversed order.",
+ mandatoryPositionals = {
+ @Param(
+ name = "sequence",
+ type = Object.class,
+ doc = "The sequence to be reversed (string, list or tuple)."
+ )
+ },
+ useLocation = true,
+ useEnvironment = true
+ )
+ private static BuiltinFunction reversed =
+ new BuiltinFunction("reversed") {
+ @SuppressWarnings("unused") // Accessed via Reflection.
+ public MutableList invoke(Object sequence, Location loc, Environment env)
+ throws EvalException {
+ // We only allow lists and strings.
+ if (sequence instanceof Map) {
+ throw new EvalException(
+ loc, "Argument to reversed() must be a sequence, not a dictionary.");
+ } else if (sequence instanceof NestedSet || sequence instanceof SkylarkNestedSet) {
+ throw new EvalException(loc, "Argument to reversed() must be a sequence, not a set.");
+ }
+ LinkedList<Object> tmpList = new LinkedList<>();
+ for (Object element : EvalUtils.toIterable(sequence, loc)) {
+ tmpList.addFirst(element);
+ }
+ return new MutableList(tmpList, env);
+ }
+ };
+
+ @SkylarkSignature(
name = "append",
objectType = MutableList.class,
returnType = Runtime.NoneType.class,
@@ -1683,8 +1718,10 @@ public class MethodLibrary {
+ "</pre>")
static final class DictModule {}
- static final List<BaseFunction> buildGlobalFunctions = ImmutableList.<BaseFunction>of(
- bool, dict, enumerate, int_, len, list, minus, range, repr, select, sorted, str, zip);
+ static final List<BaseFunction> buildGlobalFunctions =
+ ImmutableList.<BaseFunction>of(
+ bool, dict, enumerate, int_, len, list, minus, range, repr, reversed, select, sorted, str,
+ zip);
static final List<BaseFunction> skylarkGlobalFunctions =
ImmutableList.<BaseFunction>builder()
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/EnvironmentTest.java b/src/test/java/com/google/devtools/build/lib/syntax/EnvironmentTest.java
index b689fbd4bb..3e18319166 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/EnvironmentTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/EnvironmentTest.java
@@ -123,12 +123,12 @@ public class EnvironmentTest extends EvaluationTestCase {
assertEquals(Sets.newHashSet("foo", "wiz",
"False", "None", "True",
"-", "bool", "dict", "enumerate", "int", "len", "list",
- "range", "repr", "select", "sorted", "str", "zip"),
+ "range", "repr", "reversed", "select", "sorted", "str", "zip"),
outerEnv.getVariableNames());
assertEquals(Sets.newHashSet("foo", "wiz", "quux",
"False", "None", "True",
"-", "bool", "dict", "enumerate", "int", "len", "list",
- "range", "repr", "select", "sorted", "str", "zip"),
+ "range", "repr", "reversed", "select", "sorted", "str", "zip"),
innerEnv.getVariableNames());
}
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
index e76471cf6d..d1e307ae6a 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
@@ -770,6 +770,51 @@ public class MethodLibraryTest extends EvaluationTestCase {
}
@Test
+ public void testReversedWithInvalidTypes() throws Exception {
+ new BothModesTest()
+ .testIfExactError("type 'NoneType' is not iterable", "reversed(None)")
+ .testIfExactError("type 'int' is not iterable", "reversed(1)")
+ .testIfExactError(
+ "Argument to reversed() must be a sequence, not a dictionary.", "reversed({1: 3})");
+ new SkylarkTest()
+ .testIfExactError(
+ "Argument to reversed() must be a sequence, not a set.", "reversed(set([1]))");
+ }
+
+ @Test
+ public void testReversedWithLists() throws Exception {
+ new BothModesTest()
+ .testEval("reversed([])", "[]")
+ .testEval("reversed([1])", "[1]")
+ .testEval("reversed([1, 2, 3, 4, 5])", "[5, 4, 3, 2, 1]")
+ .testEval("reversed([[1, 2], 3, 4, [5]])", "[[5], 4, 3, [1, 2]]")
+ .testEval("reversed([1, 1, 1, 1, 2])", "[2, 1, 1, 1, 1]");
+ }
+
+ @Test
+ public void testReversedWithStrings() throws Exception {
+ new BothModesTest()
+ .testEval("reversed('')", "['']")
+ .testEval("reversed('a')", "['a']")
+ .testEval("reversed('abc')", "['c', 'b', 'a']")
+ .testEval("reversed('__test ')", "[' ', ' ', 't', 's', 'e', 't', '_', '_']")
+ .testEval("reversed('bbb')", "['b', 'b', 'b']");
+ }
+
+ @Test
+ public void testReversedNoSideEffects() throws Exception {
+ new SkylarkTest()
+ .testEval(
+ "def foo():\n"
+ + " x = ['a', 'b']\n"
+ + " y = reversed(x)\n"
+ + " y += ['c']\n"
+ + " return x\n"
+ + "foo()",
+ "['a', 'b']");
+ }
+
+ @Test
public void testListSlice() throws Exception {
new BothModesTest()
.testEval("[0,1,2,3][0:-1]", "[0, 1, 2]")