From dc2dbe81ff1b9363a2aa67fd09d6d14b37943d14 Mon Sep 17 00:00:00 2001 From: Matt Edwards Date: Mon, 6 Jan 2025 15:19:42 -0500 Subject: [PATCH] Release v1.1.1 (#40) - Update Nugets - Update to use the variable list for `ForExpression` * Previous version was 'v1.1.0'. Version now 'v1.1.1'. --------- Co-authored-by: Brenton Farmer Co-authored-by: MattEdwardsWaggleBee --- Directory.Build.props | 2 +- src/Hyperbee.Expressions/ForExpression.cs | 71 ++++++++++++++++--- .../Hyperbee.Expressions.Benchmark.csproj | 4 +- .../BlockAsyncBasicTests.cs | 4 +- .../Hyperbee.Expressions.Tests.csproj | 2 +- 5 files changed, 68 insertions(+), 15 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index f34844e..8f9f47e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ 1 1 - 0 + 1 diff --git a/src/Hyperbee.Expressions/ForExpression.cs b/src/Hyperbee.Expressions/ForExpression.cs index e2fae65..3241fb9 100644 --- a/src/Hyperbee.Expressions/ForExpression.cs +++ b/src/Hyperbee.Expressions/ForExpression.cs @@ -1,9 +1,11 @@ -using System.Linq.Expressions; +using System.Collections.ObjectModel; +using System.Linq.Expressions; namespace Hyperbee.Expressions; public class ForExpression : Expression { + public IEnumerable Variables { get; } public Expression Initialization { get; } public Expression Test { get; } public Expression Iteration { get; } @@ -12,33 +14,36 @@ public class ForExpression : Expression public LabelTarget BreakLabel { get; } = Label( "break" ); public LabelTarget ContinueLabel { get; } = Label( "continue" ); - internal ForExpression( Expression initialization, Expression test, Expression iteration, Expression body ) + internal ForExpression( IEnumerable variables, Expression initialization, Expression test, Expression iteration, Expression body ) { ThrowIfInvalid( test, body ); + Variables = variables; Initialization = initialization; Test = test; Iteration = iteration; Body = body; } - internal ForExpression( Expression initialization, Expression test, Expression iteration, LoopBody body ) + internal ForExpression( IEnumerable variables, Expression initialization, Expression test, Expression iteration, LoopBody body ) { ThrowIfInvalid( test, body ); + Variables = variables; Initialization = initialization; Test = test; Iteration = iteration; Body = body( BreakLabel, ContinueLabel ); } - internal ForExpression( Expression initialization, Expression test, Expression iteration, Expression body, LabelTarget breakLabel, LabelTarget continueLabel ) + internal ForExpression( IEnumerable variables, Expression initialization, Expression test, Expression iteration, Expression body, LabelTarget breakLabel, LabelTarget continueLabel ) { ThrowIfInvalid( test, body ); ArgumentNullException.ThrowIfNull( breakLabel, nameof( breakLabel ) ); ArgumentNullException.ThrowIfNull( continueLabel, nameof( continueLabel ) ); + Variables = variables; Initialization = initialization; Test = test; Iteration = iteration; @@ -64,6 +69,7 @@ private static void ThrowIfInvalid( Expression test, object body ) public override Expression Reduce() { return Block( + Variables, Initialization, Loop( IfThenElse( @@ -82,33 +88,80 @@ public override Expression Reduce() protected override Expression VisitChildren( ExpressionVisitor visitor ) { + var newVariables = VisitCollection( visitor, Variables.ToArray() ); var newInitialization = visitor.Visit( Initialization ); var newTest = visitor.Visit( Test ); var newIteration = visitor.Visit( Iteration ); var newBody = visitor.Visit( Body ); - if ( newInitialization == Initialization && newTest == Test && newIteration == Iteration && newBody == Body ) + if ( newVariables == Variables && newInitialization == Initialization && newTest == Test && newIteration == Iteration && newBody == Body ) return this; - return new ForExpression( newInitialization, newTest, newIteration, newBody, BreakLabel, ContinueLabel ); + return new ForExpression( newVariables, newInitialization, newTest, newIteration, newBody, BreakLabel, ContinueLabel ); } + + private static IEnumerable VisitCollection( ExpressionVisitor visitor, T[] nodes ) where T : Expression + { + T[] newNodes = null; + + for ( int i = 0, n = nodes.Length; i < n; i++ ) + { + var node = visitor.Visit( nodes[i] ); + + if ( newNodes != null ) + { + newNodes[i] = (T) node; + } + else if ( !ReferenceEquals( node, nodes[i] ) ) + { + newNodes = new T[n]; + for ( int j = 0; j < i; j++ ) + { + newNodes[j] = nodes[j]; + } + newNodes[i] = (T) node; + } + } + + if ( newNodes == null ) + { + return nodes; + } + + return newNodes; + } } public static partial class ExpressionExtensions { public static ForExpression For( Expression initialization, Expression test, Expression iteration, Expression body ) { - return new ForExpression( initialization, test, iteration, body ); + return new ForExpression( [], initialization, test, iteration, body ); } public static ForExpression For( Expression initialization, Expression test, Expression iteration, Expression body, LabelTarget breakLabel, LabelTarget continueLabel ) { - return new ForExpression( initialization, test, iteration, body, breakLabel, continueLabel ); + return new ForExpression( [], initialization, test, iteration, body, breakLabel, continueLabel ); } public static ForExpression For( Expression initialization, Expression test, Expression iteration, LoopBody body ) { - return new ForExpression( initialization, test, iteration, body ); + return new ForExpression( [], initialization, test, iteration, body ); + } + + public static ForExpression For( IEnumerable variables, Expression initialization, Expression test, Expression iteration, Expression body ) + { + return new ForExpression( variables, initialization, test, iteration, body ); + } + + public static ForExpression For( IEnumerable variables, Expression initialization, Expression test, Expression iteration, Expression body, LabelTarget breakLabel, LabelTarget continueLabel ) + { + return new ForExpression( variables, initialization, test, iteration, body, breakLabel, continueLabel ); + } + + public static ForExpression For( IEnumerable variables, Expression initialization, Expression test, Expression iteration, LoopBody body ) + { + return new ForExpression( variables, initialization, test, iteration, body ); } } diff --git a/test/Hyperbee.Expressions.Benchmark/Hyperbee.Expressions.Benchmark.csproj b/test/Hyperbee.Expressions.Benchmark/Hyperbee.Expressions.Benchmark.csproj index b3644f1..a675d76 100644 --- a/test/Hyperbee.Expressions.Benchmark/Hyperbee.Expressions.Benchmark.csproj +++ b/test/Hyperbee.Expressions.Benchmark/Hyperbee.Expressions.Benchmark.csproj @@ -1,4 +1,4 @@ - + Exe @@ -10,7 +10,7 @@ - + diff --git a/test/Hyperbee.Expressions.Tests/BlockAsyncBasicTests.cs b/test/Hyperbee.Expressions.Tests/BlockAsyncBasicTests.cs index cf6c8c2..df768e2 100644 --- a/test/Hyperbee.Expressions.Tests/BlockAsyncBasicTests.cs +++ b/test/Hyperbee.Expressions.Tests/BlockAsyncBasicTests.cs @@ -493,10 +493,10 @@ public async Task BlockAsync_ShouldAllowParallelBlocks_WithTaskWhenAll( Complete var iteration = PostIncrementAssign( i ); var block = BlockAsync( - [tracker, tasks, i], + [tracker, tasks], Assign( tracker, NewArrayBounds( typeof( int ), Constant( 5 ) ) ), Assign( tasks, New( typeof( List ).GetConstructors()[0] ) ), - For( initIncrement, condition, iteration, + For( [i], initIncrement, condition, iteration, Block( [temp], Assign( temp, i ), diff --git a/test/Hyperbee.Expressions.Tests/Hyperbee.Expressions.Tests.csproj b/test/Hyperbee.Expressions.Tests/Hyperbee.Expressions.Tests.csproj index 020c4d6..9f555a3 100644 --- a/test/Hyperbee.Expressions.Tests/Hyperbee.Expressions.Tests.csproj +++ b/test/Hyperbee.Expressions.Tests/Hyperbee.Expressions.Tests.csproj @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive