diff --git a/libraries/AdaptiveExpressions/BuiltinFunctions/Reverse.cs b/libraries/AdaptiveExpressions/BuiltinFunctions/Reverse.cs new file mode 100644 index 0000000000..d491cdbdb9 --- /dev/null +++ b/libraries/AdaptiveExpressions/BuiltinFunctions/Reverse.cs @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections; +using System.Linq; + +namespace AdaptiveExpressions.BuiltinFunctions +{ + /// + /// Reverses the order of the elements in a String or Array. + /// + internal class Reverse : ExpressionEvaluator + { + /// + /// Initializes a new instance of the class. + /// + public Reverse() + : base(ExpressionType.Reverse, Evaluator(), ReturnType.String | ReturnType.Array, Validator) + { + } + + private static EvaluateExpressionDelegate Evaluator() + { + return FunctionUtils.ApplyWithError( + args => + { + object result = null; + string error = null; + + if (args[0] is string string0) + { + result = new string(string0.Reverse().ToArray()); + } + else if (args[0] is IList list) + { + result = list.OfType().Reverse().ToList(); + } + else + { + error = $"{args[0]} is not a string or list."; + } + + return (result, error); + }, FunctionUtils.VerifyContainer); + } + + private static void Validator(Expression expression) + { + FunctionUtils.ValidateOrder(expression, null, ReturnType.String | ReturnType.Array); + } + } +} diff --git a/libraries/AdaptiveExpressions/ExpressionFunctions.cs b/libraries/AdaptiveExpressions/ExpressionFunctions.cs index 152e3c4f9d..9393ce6b3a 100644 --- a/libraries/AdaptiveExpressions/ExpressionFunctions.cs +++ b/libraries/AdaptiveExpressions/ExpressionFunctions.cs @@ -137,6 +137,7 @@ private static IDictionary GetStandardFunctions() new BuiltinFunctions.RemoveProperty(), new BuiltinFunctions.Replace(), new BuiltinFunctions.ReplaceIgnoreCase(), + new BuiltinFunctions.Reverse(), new BuiltinFunctions.Round(), new BuiltinFunctions.Select(), new BuiltinFunctions.SentenceCase(), diff --git a/libraries/AdaptiveExpressions/ExpressionType.cs b/libraries/AdaptiveExpressions/ExpressionType.cs index 3b52c2f653..849d3f2fae 100644 --- a/libraries/AdaptiveExpressions/ExpressionType.cs +++ b/libraries/AdaptiveExpressions/ExpressionType.cs @@ -80,6 +80,7 @@ public static class ExpressionType public const string IndicesAndValues = "indicesAndValues"; public const string Flatten = "flatten"; public const string Unique = "unique"; + public const string Reverse = "reverse"; // DateTime public const string AddDays = "addDays"; diff --git a/tests/AdaptiveExpressions.Tests/BadExpressionTests.cs b/tests/AdaptiveExpressions.Tests/BadExpressionTests.cs index fd427d5966..9270ed9377 100644 --- a/tests/AdaptiveExpressions.Tests/BadExpressionTests.cs +++ b/tests/AdaptiveExpressions.Tests/BadExpressionTests.cs @@ -356,6 +356,8 @@ public class BadExpressionTests Test("contains('hello world', 'hello', 'new')"), // should have 2 parameter Test("count(items, 1)"), // should have 1 parameter Test("count(1)"), // first param should be list or string + Test("reverse(items, 1)"), // should have 1 parameter + Test("reverse(1)"), // first param should be list or string Test("empty(1,2)"), // should have two params Test("first(items,2)"), // should have 1 param Test("last(items,2)"), // should have 1 param diff --git a/tests/AdaptiveExpressions.Tests/ExpressionParserTests.cs b/tests/AdaptiveExpressions.Tests/ExpressionParserTests.cs index 243ff06097..024424a0ae 100644 --- a/tests/AdaptiveExpressions.Tests/ExpressionParserTests.cs +++ b/tests/AdaptiveExpressions.Tests/ExpressionParserTests.cs @@ -521,6 +521,10 @@ public class ExpressionParserTests Test("count('hello')", 5), Test("count(\"hello\")", 5), Test("count(concat(hello,world))", 10), + Test("reverse('hello')", "olleh"), + Test("reverse(reverse('hello'))", "hello"), + Test("reverse(\"hello\")", "olleh"), + Test("reverse(concat(hello,world))", "dlrowolleh"), Test("replace('hello', 'l', 'k')", "hekko"), Test("replace('hello', 'L', 'k')", "hello"), Test("replace(nullObj, 'L', 'k')", string.Empty), @@ -934,6 +938,8 @@ public class ExpressionParserTests Test("concat(['a', 'b'], ['b', 'c'], ['c', 'd'])", new List { "a", "b", "b", "c", "c", "d" }), Test("count(split(hello,'e'))", 2), Test("count(createArray('h', 'e', 'l', 'l', 'o'))", 5), + Test("reverse(split(hello,'e'))", new List { "llo", "h" }), + Test("reverse(createArray('h', 'e', 'l', 'l', 'o'))", new List { "o", "l", "l", "e", "h" }), Test("empty('')", true), Test("empty('a')", false), Test("empty(bag)", false),