/// <summary>
    /// Yields all of the nodes in the tree represented by <paramref name="value"/>, starting at the bottom.
    ///
    /// <para>
    /// This is a depth-first post-order traversal.
    /// </para>
    ///
    /// <seealso cref="SelfAndDescendants"/>
    /// </summary>
    /// <example>
    /// <code>
    /// Expr expr = new Add(
    ///     new Add(
    ///         new Lit(1),
    ///         new Lit(2)
    ///     ),
    ///     new Lit(3)
    /// );
    /// Expr[] expected = new[]
    ///     {
    ///         new Lit(1),
    ///         new Lit(2),
    ///         new Add(new Lit(1), new Lit(2)),
    ///         new Lit(3),
    ///         expr
    ///     };
    /// Assert.Equal(expected, rewriter.DescendantsAndSelf(expr));
    /// </code>
    /// </example>
    /// <typeparam name="T">The rewritable tree type</typeparam>
    /// <param name="rewriter">The rewriter</param>
    /// <param name="value">The value to traverse</param>
    /// <returns>An enumerable containing all of the nodes in the tree represented by <paramref name="value"/>, starting at the bottom.</returns>
    public static IEnumerable <T> DescendantsAndSelf <T>(this IRewriter <T> rewriter, T value)
    {
        if (rewriter == null)
        {
            throw new ArgumentNullException(nameof(rewriter));
        }

        IEnumerable <T> Iterator()
        {
            var stack = new Stack <DescendantsAndSelfFrame <T> >();

            var initialArray = ArrayPool <T> .Shared.Rent(1);

            initialArray[0] = value;
            var enumerator = new DescendantsAndSelfFrame <T>(initialArray, 1);

            do
            {
                while (enumerator.MoveNext())
                {
                    stack.Push(enumerator);

                    var count = rewriter.CountChildren(enumerator.Current);
                    var array = ArrayPool <T> .Shared.Rent(count);

                    rewriter.GetChildren(array.AsSpan()[..count], enumerator.Current);
Beispiel #2
0
        /// <summary>
        /// Rewrites the specified solution.
        /// </summary>
        /// <param name="originalSolution">The solution.</param>
        /// <param name="rewriter">The rewriter.</param>
        /// <returns></returns>
        public Result <Solution> Rewrite(Solution originalSolution, IRewriter rewriter)
        => Modify(
            original: originalSolution,
            getIntermediateValues: solution => solution.ProjectIds,
            getEntry: (solution, projectId) => solution.GetProject(projectId),
            modifyEntry: project =>
        {
            var projectContext = ProjectContext.Create(project);
            if (projectContext.IsFailure)
            {
                return(Result.Fail <Project>(projectContext.Error));
            }
            else
            {
                var rewriteResult = Rewrite(projectContext.Value, rewriter);

                if (rewriteResult.IsFailure)
                {
                    return(Result.Fail <Project>(rewriteResult.Error));
                }
                else
                {
                    return(Result.Ok(rewriteResult.Value.Project));
                }
            }
        },
            getReturnValue: project => project.Solution);
Beispiel #3
0
    /// <summary>
    /// Yields all of the nodes in the tree represented by <paramref name="value"/>, starting at the top.
    ///
    /// <para>
    /// This is a depth-first pre-order traversal.
    /// </para>
    ///
    /// <seealso cref="DescendantsAndSelf"/>
    /// </summary>
    /// <example>
    /// <code>
    /// Expr expr = new Add(
    ///     new Add(
    ///         new Lit(1),
    ///         new Lit(2)
    ///     ),
    ///     new Lit(3)
    /// );
    /// Expr[] expected = new[]
    ///     {
    ///         expr,
    ///         new Add(new Lit(1), new Lit(2)),
    ///         new Lit(1),
    ///         new Lit(2),
    ///         new Lit(3),
    ///     };
    /// Assert.Equal(expected, rewriter.SelfAndDescendants(expr));
    /// </code>
    /// </example>
    /// <typeparam name="T">The rewritable tree type</typeparam>
    /// <param name="rewriter">The rewriter</param>
    /// <param name="value">The value to traverse</param>
    /// <returns>An enumerable containing all of the nodes in the tree represented by <paramref name="value"/>, starting at the top.</returns>
    public static IEnumerable <T> SelfAndDescendants <T>(this IRewriter <T> rewriter, T value)
    {
        if (rewriter == null)
        {
            throw new ArgumentNullException(nameof(rewriter));
        }

        IEnumerable <T> Iterator()
        {
            var stack = new ChunkStack <T>();

            stack.Allocate(1)[0] = value;

            try
            {
                while (!stack.IsEmpty)
                {
                    var x = stack.Pop();
                    yield return(x);

                    var count = rewriter.CountChildren(x);
                    var span  = stack.Allocate(count);
                    rewriter.GetChildren(span, x);
                    span.Reverse();  // pop them in left to right order
                }
            }
            finally
            {
                stack.Dispose();
            }
        }

        return(Iterator());
    }
Beispiel #4
0
        public PythonNode Rewrite(IRewriter visitor)
        {
            var result = visitor.Rewrite(this);

            result.Children = result.Children.Select(child => child.Rewrite(visitor)).ToList();
            return(result);
        }
    /// <summary>
    /// Yields all of the nodes in the tree represented by <paramref name="value"/> in a breadth-first traversal order.
    ///
    /// <para>
    /// This is a breadth-first pre-order traversal.
    /// </para>
    ///
    /// </summary>
    /// <typeparam name="T">The rewritable tree type</typeparam>
    /// <param name="rewriter">The rewriter</param>
    /// <param name="value">The value to traverse</param>
    /// <returns>An enumerable containing all of the nodes in the tree represented by <paramref name="value"/> in a breadth-first traversal order.</returns>
    public static IEnumerable <T> SelfAndDescendantsBreadthFirst <T>(this IRewriter <T> rewriter, T value)
    {
        if (rewriter == null)
        {
            throw new ArgumentNullException(nameof(rewriter));
        }

        IEnumerable <T> Iterator()
        {
            var queue = new PooledQueue <T>();

            queue.AllocateRight(1)[0] = value;

            try
            {
                while (queue.Count != 0)
                {
                    var x = queue.PopLeft();

                    yield return(x);

                    var count = rewriter.CountChildren(x);
                    var span  = queue.AllocateRight(count);
                    rewriter.GetChildren(span, x);
                }
            }
            finally
            {
                queue.Dispose();
            }
        }

        return(Iterator());
    }
    internal static T RewriteChildrenInternal <T>(
        this IRewriter <T> rewriter,
        Func <T, T> transformer,
        T value,
        ref ChunkStack <T> chunks
        ) => rewriter.WithChildren(
        (children, t) =>
    {
        var(r, v, f) = t;
        var changed  = false;
        for (var i = 0; i < children.Length; i++)
        {
            var child    = children[i];
            var newChild = f(child);
            children[i]  = newChild;
            changed     |= !ReferenceEquals(newChild, child);
        }

        if (changed)
        {
            return(r.SetChildren(children, v));
        }
        return(v);
    },
        (rewriter, value, transformer),
        value,
        ref chunks
        );
Beispiel #7
0
        /// <summary>
        /// Rewrites the specified document context.
        /// </summary>
        /// <param name="document">The original document.</param>
        /// <param name="rewriter">The rewriter.</param>
        /// <returns></returns>
        public Result <DocumentContext> Rewrite(DocumentContext document, IRewriter rewriter)
        {
            //only rewrite .vb and .cs
            if (document.Document.SourceCodeKind != SourceCodeKind.Regular ||
                document.Document.Name.ToLowerInvariant().EndsWith(".assemblyattributes.cs") ||
                document.Document.Name.ToLowerInvariant().EndsWith(".assemblyinfo.cs"))
            {
                return(Result.Ok(document));
            }

            var newDocResult = rewriter.Rewrite(document, _log);

            if (newDocResult.IsFailure)
            {
                return(Result.Fail <DocumentContext>(newDocResult.Error));
            }
            var newDoc = newDocResult.Value;

            var newProject        = newDoc.Project;
            var newProjectContext = ProjectContext.Create(newProject);

            if (newProjectContext.IsFailure)
            {
                return(Result.Fail <DocumentContext>(newProjectContext.Error));
            }
            else
            {
                var newDocContext =
                    newProjectContext.Value
                    .Documents
                    .Where(x => x.Document.Id == document.Document.Id)
                    .Single();
                return(Result.Ok(newDocContext));
            }
        }
    internal static ValueTask <T> RewriteChildrenInternal <T>(
        this IRewriter <T> rewriter,
        Func <T, ValueTask <T> > transformer,
        T value,
        Box <ChunkStack <T> > chunks
        ) => rewriter.WithChildren(
        async(children, t) =>
    {
        var(r, v, f) = t;
        var changed  = false;
        for (var i = 0; i < children.Length; i++)
        {
            var child        = children.Span[i];
            var newChild     = await f(child).ConfigureAwait(false);
            children.Span[i] = newChild;
            changed         |= !ReferenceEquals(newChild, child);
        }

        if (changed)
        {
            return(r.SetChildren(children.Span, v));
        }
        return(v);
    },
        (rewriter, value, transformer),
        value,
        chunks
        );
    /// <summary>
    /// Create a <see cref="Cursor{T}"/> focused on the root node of <paramref name="value"/>.
    /// </summary>
    /// <param name="rewriter">The rewriter</param>
    /// <param name="value">The root node on which the newly created <see cref="Cursor{T}"/> should be focused</param>
    /// <returns>A <see cref="Cursor{T}"/> focused on the root node of <paramref name="value"/></returns>
    public static Cursor <T> Cursor <T>(this IRewriter <T> rewriter, T value)
    {
        if (rewriter == null)
        {
            throw new ArgumentNullException(nameof(rewriter));
        }

        return(new Cursor <T>(rewriter, value));
    }
Beispiel #10
0
    internal Cursor(IRewriter <T> rewriter, T top)
    {
        if (rewriter == null)
        {
            throw new ArgumentNullException(nameof(rewriter));
        }

        _rewriter     = rewriter;
        _path         = new Stack <Step <T> >();
        _prevSiblings = new Stack <T>();
        _focus        = top;
        _nextSiblings = new Stack <T>();
    }
    /// <summary>
    /// Get the immediate children of the value.
    /// <seealso cref="IRewritable{T}.GetChildren"/>
    /// </summary>
    /// <example>
    /// Given a representation of the expression <c>(1+2)+3</c>,
    /// <code>
    /// Expr expr = new Add(
    ///     new Add(
    ///         new Lit(1),
    ///         new Lit(2)
    ///     ),
    ///     new Lit(3)
    /// );
    /// </code>
    /// <see cref="GetChildren"/> returns the immediate children of the topmost node.
    /// <code>
    /// Expr[] expected = new[]
    ///     {
    ///         new Add(
    ///             new Lit(1),
    ///             new Lit(2)
    ///         ),
    ///         new Lit(3)
    ///     };
    /// Assert.Equal(expected, rewriter.GetChildren(expr));
    /// </code>
    /// </example>
    /// <typeparam name="T">The rewritable tree type</typeparam>
    /// <param name="rewriter">The rewriter</param>
    /// <param name="value">The value</param>
    /// <returns>The immediate children of <paramref name="value"/></returns>
    public static T[] GetChildren <T>(this IRewriter <T> rewriter, T value)
    {
        if (rewriter == null)
        {
            throw new ArgumentNullException(nameof(rewriter));
        }

        var count = rewriter.CountChildren(value);
        var array = new T[count];

        rewriter.GetChildren(array, value);
        return(array);
    }
    /// <summary>
    /// Rebuild a tree by applying an asynchronous transformation function to every node from bottom to top.
    /// </summary>
    /// <example>
    /// Given a representation of the expression <c>(1+2)+3</c>,
    /// <code>
    /// Expr expr = new Add(
    ///     new Add(
    ///         new Lit(1),
    ///         new Lit(2)
    ///     ),
    ///     new Lit(3)
    /// );
    /// </code>
    /// <see cref="Rewrite{T}(IRewriter{T}, Func{T, ValueTask{T}}, T)"/> replaces the leaves of the tree with the result of calling <paramref name="transformer"/>,
    /// then replaces their parents with the result of calling <paramref name="transformer"/>, and so on.
    /// By the end, <see cref="Rewrite{T}(IRewriter{T}, Func{T, ValueTask{T}}, T)"/> has traversed the whole tree.
    /// <code>
    /// Expr expected = await transformer(new Add(
    ///     await transformer(new Add(
    ///         await transformer(new Lit(1)),
    ///         await transformer(new Lit(2))
    ///     )),
    ///     await transformer(new Lit(3))
    /// ));
    /// Assert.Equal(expected, await rewriter.Rewrite(transformer, expr));
    /// </code>
    /// </example>
    /// <typeparam name="T">The rewritable tree type</typeparam>
    /// <param name="rewriter">The rewriter</param>
    /// <param name="transformer">The asynchronous transformation function to apply to every node in the tree</param>
    /// <param name="value">The value to rewrite</param>
    /// <returns>
    /// The result of applying <paramref name="transformer"/> to every node in the tree represented by <paramref name="value"/>.
    /// </returns>
    /// <remarks>This method is not available on platforms which do not support <see cref="ValueTask"/>.</remarks>
    public static async ValueTask <T> Rewrite <T>(this IRewriter <T> rewriter, Func <T, ValueTask <T> > transformer, T value)
    {
        if (rewriter == null)
        {
            throw new ArgumentNullException(nameof(rewriter));
        }
        if (transformer == null)
        {
            throw new ArgumentNullException(nameof(transformer));
        }

        using var traversal = new RewriteAsyncTraversal <T>(rewriter, transformer);
        return(await traversal.Go(value).ConfigureAwait(false));
    }
    /// <summary>
    /// Rebuild a tree by repeatedly applying a transformation function to every node in the tree,
    /// until a fixed point is reached. <paramref name="transformer"/> should always eventually return
    /// its argument unchanged, or this method will loop.
    /// That is, <c>x.RewriteIter(transformer).SelfAndDescendants().All(x => transformer(x) == x)</c>.
    /// <para>
    /// This is typically useful when you want to put your tree into a normal form
    /// by applying a collection of rewrite rules until none of them can fire any more.
    /// </para>
    /// </summary>
    /// <typeparam name="T">The rewritable tree type</typeparam>
    /// <param name="rewriter">The rewriter</param>
    /// <param name="transformer">
    /// A transformation function to apply to every node in <paramref name="value"/> repeatedly.
    /// </param>
    /// <param name="value">The value to rewrite</param>
    /// <returns>
    /// The result of applying <paramref name="transformer"/> to every node in the tree
    /// represented by <paramref name="value"/> repeatedly until a fixed point is reached.
    /// </returns>
    public static T RewriteIter <T>(this IRewriter <T> rewriter, Func <T, T> transformer, T value) where T : class
    {
        if (rewriter == null)
        {
            throw new ArgumentNullException(nameof(rewriter));
        }
        if (transformer == null)
        {
            throw new ArgumentNullException(nameof(transformer));
        }

        using var traversal = new RewriteIterTraversal <T>(rewriter, transformer);
        return(traversal.Go(value));
    }
    /// <summary>
    /// Flatten all of the nodes in the trees represented by <paramref name="values"/>
    /// into a single value at the same time, using an aggregation function to combine
    /// nodes with the results of aggregating their children.
    /// The trees are iterated in lock-step, much like an n-ary
    /// <see cref="Enumerable.Zip{TFirst, TSecond, TResult}(IEnumerable{TFirst}, IEnumerable{TSecond}, Func{TFirst, TSecond, TResult})"/>.
    ///
    /// When trees are not the same size, the larger ones are
    /// truncated both horizontally and vertically.
    /// That is, if a pair of nodes have a different number of children,
    /// the rightmost children of the larger of the two nodes are discarded.
    /// </summary>
    /// <example>
    /// Here's an example of using <see cref="ZipFold{T, U}(IRewriter{T}, Func{T[], IEnumerable{U}, U}, T[])"/> to test if two trees are syntactically equal.
    /// <code>
    /// static bool Equals(this Expr left, Expr right)
    ///     =&gt; left.ZipFold&lt;Expr, bool&gt;(
    ///         right,
    ///         (xs, results) =&gt;
    ///         {
    ///             switch (xs[0])
    ///             {
    ///                 case Add a1 when xs[1] is Add a2:
    ///                     return results.All(x =&gt; x);
    ///                 case Lit l1 when xs[1] is Lit l2:
    ///                     return l1.Value == l2.Value;
    ///                 default:
    ///                     return false;
    ///             }
    ///         }
    ///     );
    /// </code>
    /// </example>
    /// <typeparam name="T">The rewritable tree type</typeparam>
    /// <typeparam name="U">The return type of the aggregation</typeparam>
    /// <param name="rewriter">The rewriter</param>
    /// <param name="func">The aggregation function</param>
    /// <param name="values">The trees to fold</param>
    /// <returns>The result of aggregating the two trees</returns>
    public static U ZipFold <T, U>(
        this IRewriter <T> rewriter,
        Func <T[], IEnumerable <U>, U> func,  // todo: should this be a ReadOnlySpanFunc?
        params T[] values
        )
    {
        if (rewriter == null)
        {
            throw new ArgumentNullException(nameof(rewriter));
        }
        if (func == null)
        {
            throw new ArgumentNullException(nameof(func));
        }
        if (values == null)
        {
            throw new ArgumentNullException(nameof(values));
        }

        U Go(T[] xs) => func(xs, ZipChildren(xs));

        IEnumerable <U> ZipChildren(T[] xs)
        {
            var enumerators = new IEnumerator <T> [xs.Length];

            for (var i = 0; i < xs.Length; i++)
            {
                enumerators[i] = rewriter.GetChildren(xs[i]).AsEnumerable().GetEnumerator();
            }

            while (true)
            {
                var currents = new T[xs.Length];
                for (var i = 0; i < enumerators.Length; i++)
                {
                    var e       = enumerators[i];
                    var hasNext = e.MoveNext();
                    if (!hasNext)
                    {
                        yield break;
                    }
                    currents[i] = e.Current;
                }
                yield return(Go(currents));
            }
        }

        return(Go(values));
    }
    internal static async ValueTask <R> WithChildren <T, R>(
        this IRewriter <T> rewriter,
        Func <Memory <T>, ValueTask <R> > action,
        T value,
        Box <ChunkStack <T> > chunks
        )
    {
        var count  = rewriter.CountChildren(value);
        var memory = chunks.Value.AllocateMemory(count);

        rewriter.GetChildren(memory.Span, value);
        var result = await action(memory).ConfigureAwait(false);

        chunks.Value.Free(memory);
        return(result);
    }
    /// <summary>
    /// Returns the descendant at a particular location in <paramref name="value"/>
    /// </summary>
    /// <param name="rewriter">The rewriter</param>
    /// <param name="value">The rewritable tree type</param>
    /// <param name="path">The route to take to find the descendant</param>
    /// <exception cref="InvalidOperationException">
    /// Thrown if <paramref name="path"/> leads off the edge of the tree
    /// </exception>
    /// <returns>The descendant found by following the directions in <paramref name="path"/></returns>
    public static T DescendantAt <T>(this IRewriter <T> rewriter, IEnumerable <Direction> path, T value)
    {
        if (rewriter == null)
        {
            throw new ArgumentNullException(nameof(rewriter));
        }
        if (path == null)
        {
            throw new ArgumentNullException(nameof(path));
        }

        var cursor = rewriter.Cursor(value);

        cursor.Follow(path);
        return(cursor.Focus);
    }
    /// <summary>
    /// Flattens all the nodes in the tree represented by <paramref name="value"/> into a single result,
    /// using an aggregation function to combine each node with the results of folding its children.
    /// </summary>
    /// <typeparam name="T">The rewritable tree type</typeparam>
    /// <typeparam name="U">The type of the result of aggregation</typeparam>
    /// <param name="rewriter">The rewriter</param>
    /// <param name="func">The aggregation function</param>
    /// <param name="value">The value to fold</param>
    /// <returns>The result of aggregating the tree represented by <paramref name="value"/>.</returns>
    public static U Fold <T, U>(this IRewriter <T> rewriter, SpanFunc <U, T, U> func, T value)
    {
        if (rewriter == null)
        {
            throw new ArgumentNullException(nameof(rewriter));
        }
        if (func == null)
        {
            throw new ArgumentNullException(nameof(func));
        }

        var closure = new FoldClosure <T, U>(rewriter, func);

        var result = closure.Go(value);

        closure.Dispose();

        return(result);
    }
    /// <summary>
    /// Update the immediate children of the value by applying a transformation function to each one.
    /// </summary>
    /// <typeparam name="T">The rewritable tree type</typeparam>
    /// <param name="rewriter">The rewriter</param>
    /// <param name="transformer">A transformation function to apply to each of <paramref name="value"/>'s immediate children.</param>
    /// <param name="value">The old value, whose immediate children should be transformed by <paramref name="transformer"/>.</param>
    /// <returns>A copy of <paramref name="value"/> with updated children.</returns>
    public static T RewriteChildren <T>(this IRewriter <T> rewriter, Func <T, T> transformer, T value)
    {
        if (rewriter == null)
        {
            throw new ArgumentNullException(nameof(rewriter));
        }
        if (transformer == null)
        {
            throw new ArgumentNullException(nameof(transformer));
        }

        var chunks = new ChunkStack <T>();

        var result = rewriter.RewriteChildrenInternal(transformer, value, ref chunks);

        chunks.Dispose();

        return(result);
    }
    internal static R WithChildren <T, R>(
        this IRewriter <T> rewriter,
        SpanFunc <T, R> action,
        T value,
        ref ChunkStack <T> chunks
        )
    {
        var count = rewriter.CountChildren(value);

        if (count <= 4)
        {
            return(WithChildren_Fast(rewriter, action, value, count));
        }

        var span = chunks.Allocate(count);

        rewriter.GetChildren(span, value);
        var result = action(span);

        chunks.Free(span);
        return(result);
    }
    /// <summary>
    /// Update the immediate children of the value by applying an asynchronous transformation function to each one.
    /// </summary>
    /// <typeparam name="T">The rewritable tree type</typeparam>
    /// <param name="rewriter">The rewriter</param>
    /// <param name="transformer">An asynchronous transformation function to apply to each of <paramref name="value"/>'s immediate children.</param>
    /// <param name="value">The old value, whose immediate children should be transformed by <paramref name="transformer"/>.</param>
    /// <returns>A copy of <paramref name="value"/> with updated children.</returns>
    /// <remarks>This method is not available on platforms which do not support <see cref="ValueTask"/>.</remarks>
    public static async ValueTask <T> RewriteChildren <T>(
        this IRewriter <T> rewriter,
        Func <T, ValueTask <T> > transformer,
        T value
        )
    {
        if (rewriter == null)
        {
            throw new ArgumentNullException(nameof(rewriter));
        }
        if (transformer == null)
        {
            throw new ArgumentNullException(nameof(transformer));
        }

        var chunks = new Box <ChunkStack <T> >(new ChunkStack <T>());

        var result = await rewriter.RewriteChildrenInternal(transformer, value, chunks).ConfigureAwait(false);

        chunks.Value.Dispose();

        return(result);
    }
    /// <summary>
    /// Apply an asynchronous function at a particular location in <paramref name="value"/>
    /// </summary>
    /// <param name="rewriter">The rewriter</param>
    /// <param name="value">The rewritable tree type</param>
    /// <param name="path">The route to take to find the descendant</param>
    /// <param name="transformer">An asynchronous function to calculate a replacement for the descendant</param>
    /// <exception cref="InvalidOperationException">
    /// Thrown if <paramref name="path"/> leads off the edge of the tree
    /// </exception>
    /// <returns>
    /// A copy of <paramref name="value"/> with the result of <paramref name="transformer"/> placed at the location indicated by <paramref name="path"/>
    /// </returns>
    /// <remarks>This method is not available on platforms which do not support <see cref="ValueTask"/>.</remarks>
    public static async ValueTask <T> RewriteDescendantAt <T>(this IRewriter <T> rewriter, IEnumerable <Direction> path, Func <T, ValueTask <T> > transformer, T value)
    {
        if (rewriter == null)
        {
            throw new ArgumentNullException(nameof(rewriter));
        }
        if (path == null)
        {
            throw new ArgumentNullException(nameof(path));
        }
        if (transformer == null)
        {
            throw new ArgumentNullException(nameof(transformer));
        }

        var cursor = rewriter.Cursor(value);

        cursor.Follow(path);
        cursor.Focus = await transformer(cursor.Focus).ConfigureAwait(false);

        cursor.Top();
        return(cursor.Focus);
    }
 /// <summary>
 /// Yields each node in the tree represented by <paramref name="value"/>
 /// paired with a function to replace the node, in a breadth-first traversal order.
 /// This is typically useful when you need to replace nodes one at a time,
 /// such as during mutation testing.
 ///
 /// <para>
 /// The replacement function can be seen as the "context" of the node; calling the
 /// function with a new node "plugs the hole" in the context.
 /// </para>
 ///
 /// <para>
 /// This is a breadth-first pre-order traversal.
 /// </para>
 ///
 /// <seealso cref="SelfAndDescendants"/>
 /// <seealso cref="ChildrenInContext"/>
 /// <seealso cref="DescendantsAndSelfInContext"/>
 /// </summary>
 /// <param name="rewriter">The rewriter</param>
 /// <param name="value">The value to get the contexts for the descendants</param>
 public static IEnumerable <(T item, Func <T, T> replace)> SelfAndDescendantsInContextBreadthFirst <T>(this IRewriter <T> rewriter, T value)
 {
     if (rewriter == null)
 public RewriteIterAsyncTraversal(IRewriter <T> rewriter, Func <T, ValueTask <T> > transformer) : base(rewriter, transformer)
 {
 }
 public FoldClosure(IRewriter <T> rewriter, SpanFunc <U, T, U> func) : base(rewriter)
 {
     _func = func;
 }
 /// <summary>
 /// Yields each node in the tree represented by <paramref name="value"/>
 /// paired with a function to replace the node, starting at the bottom.
 /// This is typically useful when you need to replace nodes one at a time,
 /// such as during mutation testing.
 ///
 /// <para>
 /// The replacement function can be seen as the "context" of the node; calling the
 /// function with a new node "plugs the hole" in the context.
 /// </para>
 ///
 /// <para>
 /// This is a depth-first post-order traversal.
 /// </para>
 ///
 /// <seealso cref="DescendantsAndSelf"/>
 /// <seealso cref="ChildrenInContext"/>
 /// <seealso cref="SelfAndDescendantsInContext"/>
 /// </summary>
 /// <param name="rewriter">The rewriter</param>
 /// <param name="value">The value to get the contexts for the descendants</param>
 public static IEnumerable <(T item, Func <T, T> replace)> DescendantsAndSelfInContext <T>(this IRewriter <T> rewriter, T value)
 {
     if (rewriter == null)
 private static R WithChildren_Fast <T, R>(this IRewriter <T> rewriter, SpanFunc <T, R> action, T value, int count)
 {
     var buffer = new FixedSizeBuffer4 <T>();
     var span   = buffer.AsSpan()[..count];
 public RewriteTraversal(IRewriter <T> rewriter, Func <T, T> transformer) : base(rewriter)
 {
     Transformer = transformer;
 }
 public RewriteIterTraversal(IRewriter <T> rewriter, Func <T, T> transformer) : base(rewriter, transformer)
 {
 }
Beispiel #29
0
 /// <summary>
 /// Rewrites the specified original project context.
 /// </summary>
 /// <param name="originalProjectContext">The original project context.</param>
 /// <param name="rewriter">The rewriter.</param>
 /// <returns></returns>
 public Result <ProjectContext> Rewrite(ProjectContext originalProjectContext, IRewriter rewriter)
 => Modify(
     original: originalProjectContext,
     getIntermediateValues: projectContext => projectContext.Project.DocumentIds,
     getEntry: (projectContext, documentId) => projectContext.Documents.Where(x => x.Document.Id == documentId).Single(),
     modifyEntry: documentContext =>
 {
     var rewriteResult = Rewrite(documentContext, rewriter);
     return(rewriteResult);
 },
     getReturnValue: documentContext => documentContext.ProjectContext);