diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Config/PowerFxConfig.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Config/PowerFxConfig.cs index 8942026dde..b57f36608f 100644 --- a/src/libraries/Microsoft.PowerFx.Core/Public/Config/PowerFxConfig.cs +++ b/src/libraries/Microsoft.PowerFx.Core/Public/Config/PowerFxConfig.cs @@ -52,9 +52,6 @@ public SymbolTable SymbolTable set => _symbolTable = value; } - // Remove this: https://github.com/microsoft/Power-Fx/issues/2821 - internal readonly Dictionary AdditionalFunctions = new (); - [Obsolete("Use Config.EnumStore or symboltable directly")] internal EnumStoreBuilder EnumStoreBuilder => InternalConfigSymbols.EnumStoreBuilder; diff --git a/src/libraries/Microsoft.PowerFx.Interpreter/Environment/PowerFxConfigExtensions.cs b/src/libraries/Microsoft.PowerFx.Interpreter/Environment/PowerFxConfigExtensions.cs index 85c28390c9..e11deaf31b 100644 --- a/src/libraries/Microsoft.PowerFx.Interpreter/Environment/PowerFxConfigExtensions.cs +++ b/src/libraries/Microsoft.PowerFx.Interpreter/Environment/PowerFxConfigExtensions.cs @@ -67,15 +67,14 @@ public static void EnableRegExFunctions(this PowerFxConfig config, TimeSpan regE { RegexTypeCache regexTypeCache = new (regexCacheSize); - foreach (KeyValuePair func in Library.RegexFunctions(regExTimeout, regexTypeCache)) + foreach (TexlFunction func in Library.RegexFunctions(regExTimeout, regexTypeCache)) { - if (config.ComposedConfigSymbols.Functions.AnyWithName(func.Key.Name)) + if (config.ComposedConfigSymbols.Functions.AnyWithName(func.Name)) { throw new InvalidOperationException("Cannot add RegEx functions more than once."); } - config.InternalConfigSymbols.AddFunction(func.Key); - config.AdditionalFunctions.Add(func.Key, func.Value); + config.InternalConfigSymbols.AddFunction(func); } } diff --git a/src/libraries/Microsoft.PowerFx.Interpreter/EvalVisitor.cs b/src/libraries/Microsoft.PowerFx.Interpreter/EvalVisitor.cs index 36994f146e..e287d552ce 100644 --- a/src/libraries/Microsoft.PowerFx.Interpreter/EvalVisitor.cs +++ b/src/libraries/Microsoft.PowerFx.Interpreter/EvalVisitor.cs @@ -404,9 +404,6 @@ public override async ValueTask Visit(CallNode node, EvalVisitorCo FormulaValue result; - // Remove this: https://github.com/microsoft/Power-Fx/issues/2821 - IReadOnlyDictionary extraFunctions = _services.GetService>(); - try { IFunctionInvoker invoker = GetInvoker(func); @@ -430,10 +427,6 @@ public override async ValueTask Visit(CallNode node, EvalVisitorCo { result = await asyncFunc.InvokeAsync(args, _cancellationToken).ConfigureAwait(false); } - else if (extraFunctions?.TryGetValue(func, out asyncFunc) == true) - { - result = await asyncFunc.InvokeAsync(args, _cancellationToken).ConfigureAwait(false); - } else if (func is IAsyncTexlFunction4 asyncFunc4) { // https://github.com/microsoft/Power-Fx/issues/2818 diff --git a/src/libraries/Microsoft.PowerFx.Interpreter/Functions/LibraryRegEx.cs b/src/libraries/Microsoft.PowerFx.Interpreter/Functions/LibraryRegEx.cs index a67a0a0342..1cf23900e7 100644 --- a/src/libraries/Microsoft.PowerFx.Interpreter/Functions/LibraryRegEx.cs +++ b/src/libraries/Microsoft.PowerFx.Interpreter/Functions/LibraryRegEx.cs @@ -31,7 +31,7 @@ internal static partial class Library /// Timeout duration for regular expression execution. Default is 1 second. /// Regular expression type cache. /// - internal static Dictionary RegexFunctions(TimeSpan regexTimeout, RegexTypeCache regexCache) + internal static IEnumerable RegexFunctions(TimeSpan regexTimeout, RegexTypeCache regexCache) { if (regexTimeout == TimeSpan.Zero) { @@ -43,14 +43,47 @@ internal static Dictionary RegexFunctions(Time throw new ArgumentOutOfRangeException(nameof(regexTimeout), "Timeout duration for regular expression execution must be positive."); } - return new Dictionary() + return new TexlFunction[] { - { new IsMatchFunction(regexCache), new IsMatchImplementation(regexTimeout) }, - { new MatchFunction(regexCache), new MatchImplementation(regexTimeout) }, - { new MatchAllFunction(regexCache), new MatchAllImplementation(regexTimeout) } + new IsMatchImpl(regexCache, new IsMatchImplementation(regexTimeout)), + new MatchImpl(regexCache, new MatchImplementation(regexTimeout)), + new MatchAllImpl(regexCache, new MatchAllImplementation(regexTimeout)), }; } + internal sealed class IsMatchImpl : IsMatchFunction, IAsyncTexlFunction + { + private readonly IAsyncTexlFunction _inner; + + public IsMatchImpl(RegexTypeCache regexCache, IAsyncTexlFunction inner) + : base(regexCache) => _inner = inner; + + public Task InvokeAsync(FormulaValue[] args, CancellationToken cancellationToken) + => _inner.InvokeAsync(args, cancellationToken); + } + + internal sealed class MatchImpl : MatchFunction, IAsyncTexlFunction + { + private readonly IAsyncTexlFunction _inner; + + public MatchImpl(RegexTypeCache regexCache, IAsyncTexlFunction inner) + : base(regexCache) => _inner = inner; + + public Task InvokeAsync(FormulaValue[] args, CancellationToken cancellationToken) + => _inner.InvokeAsync(args, cancellationToken); + } + + internal sealed class MatchAllImpl : MatchAllFunction, IAsyncTexlFunction + { + private readonly IAsyncTexlFunction _inner; + + public MatchAllImpl(RegexTypeCache regexCache, IAsyncTexlFunction inner) + : base(regexCache) => _inner = inner; + + public Task InvokeAsync(FormulaValue[] args, CancellationToken cancellationToken) + => _inner.InvokeAsync(args, cancellationToken); + } + internal class IsMatchImplementation : RegexCommonImplementation { private readonly TimeSpan _regexTimeout; diff --git a/src/libraries/Microsoft.PowerFx.Interpreter/ParsedExpression.cs b/src/libraries/Microsoft.PowerFx.Interpreter/ParsedExpression.cs index ce8ad19063..227607205d 100644 --- a/src/libraries/Microsoft.PowerFx.Interpreter/ParsedExpression.cs +++ b/src/libraries/Microsoft.PowerFx.Interpreter/ParsedExpression.cs @@ -86,7 +86,6 @@ internal static IExpressionEvaluator GetEvaluator(this CheckResult result, Stack _globals = globals, _allSymbols = result.Symbols, _parameterSymbolTable = result.Parameters, - _additionalFunctions = result.Engine.Config.AdditionalFunctions }; return expr; @@ -126,7 +125,6 @@ internal class ParsedExpression : IExpressionEvaluator internal ReadOnlySymbolValues _globals; internal ReadOnlySymbolTable _allSymbols; internal ReadOnlySymbolTable _parameterSymbolTable; - internal IReadOnlyDictionary _additionalFunctions; internal ParsedExpression(IntermediateNode irnode, ScopeSymbol topScope, StackDepthCounter stackMarker, CultureInfo cultureInfo = null) { @@ -150,12 +148,6 @@ public async Task EvalAsync(CancellationToken cancellationToken, I hasInnerServices = true; } - if (_additionalFunctions != null && _additionalFunctions.Any()) - { - innerServices.AddService(_additionalFunctions); - hasInnerServices = true; - } - RuntimeConfig runtimeConfig2 = new RuntimeConfig { Values = symbolValues, diff --git a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/Helpers/LibraryRegEx_Compare.cs b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/Helpers/LibraryRegEx_Compare.cs index c8d79bbbc3..8a8fbe9eca 100644 --- a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/Helpers/LibraryRegEx_Compare.cs +++ b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/Helpers/LibraryRegEx_Compare.cs @@ -25,19 +25,18 @@ public static void EnableRegExFunctions(PowerFxConfig config, TimeSpan regExTime { RegexTypeCache regexTypeCache = new (regexCacheSize); - foreach (KeyValuePair func in RegexFunctions(regExTimeout, regexTypeCache, includeDotNet, includeNode, includePCRE2)) + foreach (TexlFunction func in RegexFunctions(regExTimeout, regexTypeCache, includeDotNet, includeNode, includePCRE2)) { - if (config.ComposedConfigSymbols.Functions.AnyWithName(func.Key.Name)) + if (config.ComposedConfigSymbols.Functions.AnyWithName(func.Name)) { throw new InvalidOperationException("Cannot add RegEx functions more than once."); } - config.InternalConfigSymbols.AddFunction(func.Key); - config.AdditionalFunctions.Add(func.Key, func.Value); + config.InternalConfigSymbols.AddFunction(func); } } - internal static Dictionary RegexFunctions(TimeSpan regexTimeout, RegexTypeCache regexCache, bool includeDotNet, bool includeNode, bool includePCRE2) + internal static IEnumerable RegexFunctions(TimeSpan regexTimeout, RegexTypeCache regexCache, bool includeDotNet, bool includeNode, bool includePCRE2) { if (regexTimeout == TimeSpan.Zero) { @@ -49,11 +48,11 @@ internal static Dictionary RegexFunctions(Time throw new ArgumentOutOfRangeException(nameof(regexTimeout), "Timeout duration for regular expression execution must be positive."); } - return new Dictionary() + return new TexlFunction[] { - { new IsMatchFunction(regexCache), new Compare_IsMatchImplementation(regexTimeout, includeDotNet, includeNode, includePCRE2) }, - { new MatchFunction(regexCache), new Compare_MatchImplementation(regexTimeout, includeDotNet, includeNode, includePCRE2) }, - { new MatchAllFunction(regexCache), new Compare_MatchAllImplementation(regexTimeout, includeDotNet, includeNode, includePCRE2) } + new Library.IsMatchImpl(regexCache, new Compare_IsMatchImplementation(regexTimeout, includeDotNet, includeNode, includePCRE2)), + new Library.MatchImpl(regexCache, new Compare_MatchImplementation(regexTimeout, includeDotNet, includeNode, includePCRE2)), + new Library.MatchAllImpl(regexCache, new Compare_MatchAllImplementation(regexTimeout, includeDotNet, includeNode, includePCRE2)), }; } diff --git a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/Helpers/LibraryRegEx_NodeJS.cs b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/Helpers/LibraryRegEx_NodeJS.cs index bb32bac419..efbfc8db1b 100644 --- a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/Helpers/LibraryRegEx_NodeJS.cs +++ b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/Helpers/LibraryRegEx_NodeJS.cs @@ -242,19 +242,18 @@ public static void EnableRegExFunctions(PowerFxConfig config, TimeSpan regExTime { RegexTypeCache regexTypeCache = new (regexCacheSize); - foreach (KeyValuePair func in RegexFunctions(regExTimeout, regexTypeCache)) + foreach (TexlFunction func in RegexFunctions(regExTimeout, regexTypeCache)) { - if (config.SymbolTable.Functions.AnyWithName(func.Key.Name)) + if (config.SymbolTable.Functions.AnyWithName(func.Name)) { throw new InvalidOperationException("Cannot add RegEx functions more than once."); } - config.SymbolTable.AddFunction(func.Key); - config.AdditionalFunctions.Add(func.Key, func.Value); + config.SymbolTable.AddFunction(func); } } - internal static Dictionary RegexFunctions(TimeSpan regexTimeout, RegexTypeCache regexCache) + internal static IEnumerable RegexFunctions(TimeSpan regexTimeout, RegexTypeCache regexCache) { if (regexTimeout == TimeSpan.Zero) { @@ -266,11 +265,11 @@ internal static Dictionary RegexFunctions(Time throw new ArgumentOutOfRangeException(nameof(regexTimeout), "Timeout duration for regular expression execution must be positive."); } - return new Dictionary() + return new TexlFunction[] { - { new IsMatchFunction(regexCache), new NodeJS_IsMatchImplementation(regexTimeout) }, - { new MatchFunction(regexCache), new NodeJS_MatchImplementation(regexTimeout) }, - { new MatchAllFunction(regexCache), new NodeJS_MatchAllImplementation(regexTimeout) } + new Library.IsMatchImpl(regexCache, new NodeJS_IsMatchImplementation(regexTimeout)), + new Library.MatchImpl(regexCache, new NodeJS_MatchImplementation(regexTimeout)), + new Library.MatchAllImpl(regexCache, new NodeJS_MatchAllImplementation(regexTimeout)), }; } diff --git a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/Helpers/LibraryRegEx_PCRE2.cs b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/Helpers/LibraryRegEx_PCRE2.cs index 9972034234..98b31efa45 100644 --- a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/Helpers/LibraryRegEx_PCRE2.cs +++ b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/Helpers/LibraryRegEx_PCRE2.cs @@ -437,19 +437,18 @@ public static void EnableRegExFunctions(PowerFxConfig config, TimeSpan regExTime { RegexTypeCache regexTypeCache = new (regexCacheSize); - foreach (KeyValuePair func in RegexFunctions(regExTimeout, regexTypeCache)) + foreach (TexlFunction func in RegexFunctions(regExTimeout, regexTypeCache)) { - if (config.SymbolTable.Functions.AnyWithName(func.Key.Name)) + if (config.SymbolTable.Functions.AnyWithName(func.Name)) { throw new InvalidOperationException("Cannot add RegEx functions more than once."); } - config.SymbolTable.AddFunction(func.Key); - config.AdditionalFunctions.Add(func.Key, func.Value); + config.SymbolTable.AddFunction(func); } } - internal static Dictionary RegexFunctions(TimeSpan regexTimeout, RegexTypeCache regexCache) + internal static IEnumerable RegexFunctions(TimeSpan regexTimeout, RegexTypeCache regexCache) { if (regexTimeout == TimeSpan.Zero) { @@ -461,11 +460,11 @@ internal static Dictionary RegexFunctions(Time throw new ArgumentOutOfRangeException(nameof(regexTimeout), "Timeout duration for regular expression execution must be positive."); } - return new Dictionary() + return new TexlFunction[] { - { new IsMatchFunction(regexCache), new PCRE2_IsMatchImplementation(regexTimeout) }, - { new MatchFunction(regexCache), new PCRE2_MatchImplementation(regexTimeout) }, - { new MatchAllFunction(regexCache), new PCRE2_MatchAllImplementation(regexTimeout) } + new Library.IsMatchImpl(regexCache, new PCRE2_IsMatchImplementation(regexTimeout)), + new Library.MatchImpl(regexCache, new PCRE2_MatchImplementation(regexTimeout)), + new Library.MatchAllImpl(regexCache, new PCRE2_MatchAllImplementation(regexTimeout)), }; } diff --git a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/TextTests.cs b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/TextTests.cs index 262121a4e2..be5f1d0bce 100644 --- a/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/TextTests.cs +++ b/src/tests/Microsoft.PowerFx.Interpreter.Tests.Shared/TextTests.cs @@ -35,7 +35,6 @@ public void TextCatchIllegalFormatException() _allSymbols = symbols, _parameterSymbolTable = symbols, _globals = values, - _additionalFunctions = new Dictionary(), }; // This test