Skip to content

Commit

Permalink
Added an ability to inspect stack machine chains
Browse files Browse the repository at this point in the history
  • Loading branch information
YohDeadfall committed Jul 9, 2024
1 parent 0e4df5c commit af5d7b9
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 3 deletions.
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,19 @@ using Kinetic.Data;
BindingPlugins.PropertyAccessors.Insert(2, new KineticPropertyAccessor());
```

> This approach is incompatible with compiled bindings since XAMLIL has no idea about Kinetic properties and treats them as usual properties. Ability to create compiled bindings in XAML will come in one of next releases, but it's already available in code behind using `OneWay` and `TwoWay` methods of `Binding` type in `Kinetic.Data`.
> This approach is incompatible with compiled bindings since XAMLIL has no idea about Kinetic properties and treats them as usual properties. Ability to create compiled bindings in XAML will come in one of next releases, but it's already available in code behind using `OneWay` and `TwoWay` methods of `Binding` type in `Kinetic.Data`
## Debugging

Kinetic assembles a chain of LINQ calls into a single state machine, so it's possible to inspect it in the debugger as a single list. No more diving into internal fields, checking subscribers of each operator to find what you want.

As an example, the `observer` variable can be seen in the debugger as a list of 4 state machines:

```csharp
var source = new PublishSubject<int>();
var observer = source // + observable
// ├ ObserverStateMachine
.Where(x => x > 0) // ├ WhereStateMachind
.Select(x => x + 1) // ├ SelectStateMachineelectStateMachine
.ToObservable(); // └ ObservableStateMachine
```
9 changes: 8 additions & 1 deletion src/Kinetic/Linq/StateMachines/StateMachine.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using System;
using System.Diagnostics;

namespace Kinetic.Linq.StateMachines;

public abstract class StateMachine
{
private protected StateMachine() { }

internal abstract StateMachine? Continuation { get; }
}

public abstract class StateMachine<T> : StateMachine, IObserver<T>
Expand All @@ -20,15 +23,19 @@ internal static StateMachine<T> Create<TStateMachine>(ref TStateMachine stateMac
new StateMachine<T, TStateMachine>(ref stateMachine);
}

[DebuggerTypeProxy(typeof(StateMachineDebugView<,>))]
public class StateMachine<T, TStateMachine> : StateMachine<T>
where TStateMachine : struct, IStateMachine<T>
{
protected StateMachineReference<T, TStateMachine> Reference { get; }
protected internal StateMachineReference<T, TStateMachine> Reference { get; }

public StateMachine(ref TStateMachine stateMachine) :
this(new StateMachineReference<T, TStateMachine>(ref stateMachine))
{ }

internal override StateMachine? Continuation =>
Reference.Target.Continuation;

public StateMachine(StateMachineReference<T, TStateMachine> stateMchine) =>
Reference = stateMchine;

Expand Down
4 changes: 3 additions & 1 deletion src/Kinetic/Linq/StateMachines/StateMachineBox.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

Expand Down Expand Up @@ -37,6 +38,7 @@ internal ref TStateMachine ReferenceTo<T, TStateMachine>(IntPtr offset)
}
}

[DebuggerTypeProxy(typeof(StateMachineBoxDebugView<,>))]
public abstract class StateMachineBox<T, TStateMachine> : StateMachineBox, IObserver<T>
where TStateMachine : struct, IStateMachine<T>
{
Expand All @@ -47,7 +49,7 @@ public abstract class StateMachineBox<T, TStateMachine> : StateMachineBox, IObse
ref Unsafe.As<TStateMachine, byte>(ref _stateMachine),
length: Unsafe.SizeOf<TStateMachine>());

protected ref TStateMachine StateMachine => ref _stateMachine;
protected internal ref TStateMachine StateMachine => ref _stateMachine;

protected StateMachineBox(in TStateMachine stateMachine) =>
_stateMachine = stateMachine;
Expand Down
24 changes: 24 additions & 0 deletions src/Kinetic/Linq/StateMachines/StateMachineBoxDebugView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Collections.Generic;
using System.Diagnostics;

namespace Kinetic.Linq.StateMachines;

internal sealed class StateMachineBoxDebugView<T, TStateMachine>
where TStateMachine : struct, IStateMachine<T>
{
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public IReadOnlyList<StateMachine> Items { get; }

public StateMachineBoxDebugView(StateMachineBox<T, TStateMachine> box)
{
var items = new List<StateMachine>();
var reference = box.StateMachine.Reference as StateMachine;
while (reference is { })
{
items.Add(reference);
reference = reference.Continuation;
}

Items = items.ToArray();
}
}
16 changes: 16 additions & 0 deletions src/Kinetic/Linq/StateMachines/StateMachineDebugView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Diagnostics;

namespace Kinetic.Linq.StateMachines;

internal sealed class StateMachineDebugView<T, TStateMachine>
where TStateMachine : struct, IStateMachine<T>
{
private readonly StateMachine<T, TStateMachine> _stateMachine;

[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public TStateMachine StateMachine =>
_stateMachine.Reference.Target;

public StateMachineDebugView(StateMachine<T, TStateMachine> stateMachine) =>
_stateMachine = stateMachine;
}

0 comments on commit af5d7b9

Please sign in to comment.