<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged procedural</title>
<link>https://coderlegion.com/tag/procedural</link>
<description>Powered by Question2Answer</description>
<item>
<title>DevLog 2025801: Procedural Context Type</title>
<link>https://coderlegion.com/4381/devlog-2025801-procedural-context-type</link>
<description>&lt;h3 id=&quot;overview&quot;&gt;Overview&lt;/h3&gt;
&lt;p&gt;In our pursuit to challenge existing visual paradigms and establish the next-generation general-purpose visual programming system, we've studied, borrowed from, and questioned many design elements of existing systems.&lt;/p&gt;
&lt;p&gt;An area of innovation in Divooka is its hybrid use of dataflow and procedural contexts - each suited for particular use cases.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l5wo9dlxp01octrgexw0.png&quot; alt=&quot;Mixed Context&quot;&gt;&lt;/p&gt;
&lt;p&gt;Another innovation, still in its infancy and improving through trial and error, is what we call the &lt;strong&gt;procedural context base type&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;introduction&quot;&gt;Introduction&lt;/h3&gt;
&lt;p&gt;The need for this concept emerged as we integrated procedural contexts and re-examined the pain points of working with advanced visual programming systems like Unreal Blueprint. Changing the base type of Blueprints often leads to disastrous outcomes.&lt;/p&gt;
&lt;p&gt;We aim to provide a smoother experience. In Divooka, the procedural &quot;base type&quot; is a toggle - you can quickly switch a graph to a different base type. Everything that isn't type-dependent continues to work, and any function that is type-dependent simply indicates so.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4b3m2d9plfvxrr23qkdf.png&quot; alt=&quot;Picker&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;components&quot;&gt;Components&lt;/h3&gt;
&lt;p&gt;The procedural base type introduces four important concepts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Procedural base type (current anchor)&lt;/strong&gt;: The current graph's base, representing the instance that functions in the graph are called on.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Procedural runner for any given base type&lt;/strong&gt;: When a run is triggered, Divooka allows a custom runner to determine what actually happens. In a typical program, this runner might seek the &quot;entry&quot; function (e.g., &lt;code&gt;Start&lt;/code&gt;) and execute from there. In higher-level frameworks, it might look for recognizable event bindings.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Procedural base type instance override&lt;/strong&gt;: By default, the specified base type is instantiated at runtime to provide a concrete instance. However, the runtime can also supply a compatible instance for the graph's behavior to operate on. This allows flexibility and decouples implementation (runtime instance) from behavior specification (graph design).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Divooka graph-baked procedural instance type&lt;/strong&gt;: It may be desirable to directly convert or interpret a graph as a concrete type. The main benefit is being able to pass the graph as a type for further processing. This feature is not yet implemented.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Based on the above, three key objects are involved in evaluating a procedural context graph:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Executer&lt;/strong&gt;: Provides the logic and mechanisms to fetch and evaluate specific execution paths in the procedural graph.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Runner&lt;/strong&gt;: Determines what to run and in what order, on an event level. It may also provide additional runtime data required by the instance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Instance&lt;/strong&gt;: Represents the runtime state of the graph.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;
&lt;p&gt;In summary, a Divooka graph is a data structure that specifies behavior, while the runtime interprets and is responsible for actual execution. This makes Divooka a data-driven and highly extensible programming system suitable for various scenarios.&lt;/p&gt;
&lt;p&gt;By combining the scripting nature of Divooka graphs with the compiled/JIT-accelerated nature of the runtime, Divooka offers both flexibility and dynamic richness - while minimizing friction in program development.&lt;/p&gt;
</description>
<category>Divooka</category>
<guid isPermaLink="true">https://coderlegion.com/4381/devlog-2025801-procedural-context-type</guid>
<pubDate>Sat, 02 Aug 2025 01:47:41 +0000</pubDate>
</item>
<item>
<title>DevLog 20250708: Procedural Context Visual Debugger in Divooka</title>
<link>https://coderlegion.com/3830/devlog-20250708-procedural-context-visual-debugger-in-divooka</link>
<description>&lt;h3 id=&quot;overview-1&quot;&gt;Overview&lt;/h3&gt;
&lt;p&gt;How difficult is it to achieve Unreal Engine-style procedural context debugging?&lt;/p&gt;
&lt;p&gt;Turns out, it might be easier than expected.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/99z4fa3t53psaf6kzs0z.png&quot; alt=&quot;Unreal Debugging&quot;&gt;&lt;/p&gt;
&lt;p&gt;In this dev log, we won't implement all the fancy animations or full-featured GUI yet, but we &lt;em&gt;will&lt;/em&gt; derive a practical, functional debugger GUI. This interface allows users to step through a procedural program and observe its execution flow in real time.&lt;/p&gt;
&lt;h3 id=&quot;the-debugging-problem&quot;&gt;The Debugging Problem&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t1qcjwrsujpfy96tn2us.gif&quot; alt=&quot;Debugging Process&quot;&gt;&lt;/p&gt;
&lt;p&gt;Procedural contexts are hard - not necessarily to implement (they're actually simpler than dataflow contexts in interpretative runtimes, where you just step over nodes), but hard &lt;em&gt;for users&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The main issue is statefulness: once there's state, there's the potential for mistakes, side effects, and confusion.&lt;/p&gt;
&lt;p&gt;From an implementation standpoint, the hard part is debugging. Without visibility into execution, it's difficult to guess what's happening. That's why programming languages without IDEs often fall back on &lt;code&gt;Print&lt;/code&gt; statements to inspect runtime states. This approach quickly breaks down with larger programs or those involving intricate state transitions.&lt;/p&gt;
&lt;p&gt;Even Python - often used without an IDE - includes a built-in debugger in IDLE (&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.cs.uky.edu/~keen/help/debug-tutorial/debug.html&quot;&gt;see tutorial&lt;/a&gt;). It's essential when working with complex logic.&lt;/p&gt;
&lt;h3 id=&quot;approach&quot;&gt;Approach&lt;/h3&gt;
&lt;p&gt;Let's start by clarifying the setup: the current implementation of the Divooka graph editor (Neo) is done in WPF, using an interpretative runtime.&lt;/p&gt;
&lt;p&gt;For drawing the GUI, we can use standard XAML data bindings and a few button states:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-xaml&quot;&gt;&amp;lt;StackPanel&amp;gt;
&amp;lt;!--Start--&amp;gt;
&amp;lt;Button Style=&quot;{StaticResource IconButtonStyle}&quot; Click=&quot;ProceduralContextRunGraphWithoutDebugging_Clicked&quot; ToolTip=&quot;Run and wait for the process to finish.&quot; Visibility=&quot;{Binding EvaluatingGraph, Converter={converters:BooleanToVisibilityConverter Negate=True}}&quot;/&amp;gt;

&amp;lt;!--Continue--&amp;gt;
&amp;lt;Button Style=&quot;{StaticResource DebugButtonStyle}&quot; Content=&quot;Continue&quot; Click=&quot;ProceduralContextContinueWithoutStepping_Clicked&quot; ToolTip=&quot;Skip debugging and continue the process to completion.&quot; Visibility=&quot;{Binding IsProceduralStepping, Converter={converters:BooleanToVisibilityConverter}}&quot;/&amp;gt;

&amp;lt;!--Step--&amp;gt;
&amp;lt;StackPanel Visibility=&quot;{Binding EvaluatingGraph, Converter={converters:BooleanToVisibilityConverter Negate=True}}&quot;&amp;gt;
&amp;lt;Button Style=&quot;{StaticResource DebugButtonStyle}&quot; Content=&quot;Step&quot; Click=&quot;ProceduralContextStartDebuggingGraph_Clicked&quot; ToolTip=&quot;Step into the process and observe each execution step.&quot; Visibility=&quot;{Binding IsProceduralStepping, Converter={converters:BooleanToVisibilityConverter Negate=True}}&quot;/&amp;gt;
&amp;lt;/StackPanel&amp;gt;

&amp;lt;!--Next Step--&amp;gt;
&amp;lt;Button Style=&quot;{StaticResource DebugButtonStyle}&quot; Content=&quot;Next&quot; Click=&quot;ProceduralContextContinueThroughGraph_Clicked&quot; ToolTip=&quot;Execute (step over) the next step in the process.&quot;  Visibility=&quot;{Binding IsProceduralStepping, Converter={converters:BooleanToVisibilityConverter}}&quot; IsEnabled=&quot;{Binding IsProceduralPaused}&quot;/&amp;gt;

&amp;lt;Button Style=&quot;{StaticResource DebugButtonStyle}&quot; Content=&quot;Finish&quot; Click=&quot;ProceduralContextFinishDebuggingGraph_Clicked&quot; ToolTip=&quot;Stop debugging the current process.&quot; Visibility=&quot;{Binding IsProceduralStepping, Converter={converters:BooleanToVisibilityConverter}}&quot;/&amp;gt;

&amp;lt;Button Style=&quot;{StaticResource DebugButtonStyle}&quot; Content=&quot;Pause&quot; Click=&quot;ProceduralContextPauseExecution_Clicked&quot; ToolTip=&quot;Pause execution of the current process.&quot; Visibility=&quot;{Binding EvaluatingGraph, Converter={converters:BooleanToVisibilityConverter}}&quot; IsEnabled=&quot;{Binding IsProceduralPaused, Converter={StaticResource InvertBooleanConverter}}&quot;/&amp;gt;
&amp;lt;/StackPanel&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;stepping-through-execution&quot;&gt;Stepping Through Execution&lt;/h4&gt;
&lt;p&gt;Initially, I thought we needed a dedicated execution runtime for stepping, due to the complexity of node interpretation. However, it turns out we can simply inject &quot;breakpoints&quot; during interpretation. The simplest way to achieve this in C# with multithreading is by using a &lt;code&gt;ManualResetEventSlim&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c#&quot;&gt;// ── MainWindow.xaml.cs (WPF) ──
public partial class MainWindow : Window
{
// starts signaled (i.e. not paused)
    private readonly ManualResetEventSlim _pauseEvent = new ManualResetEventSlim(true);
    private readonly Executer _executer;

    public MainWindow()
    {
        InitializeComponent();
        _executer = new Executer(_pauseEvent);
    }

    private async void StartButton_Click(object sender, RoutedEventArgs e)
    {
// Run on thread-pool, but because we 'await', continuation
        // (Finish…) runs back on the UI thread.
        await Task.Run(() =&amp;gt; _executer.ExecuteGraph());
        FinishProceduralContextDebuggingSession();
    }

    private void PauseButton_Click(object sender, RoutedEventArgs e)
    {
// next time the worker hits Wait(), it will block
        _pauseEvent.Reset();
    }

    private void ResumeButton_Click(object sender, RoutedEventArgs e)
    {
// unblocks the worker
        _pauseEvent.Set();
    }
}

// ── Executer.cs ──
public class Executer
{
    private readonly ManualResetEventSlim _pauseEvent;
    private readonly Random _random = new Random();

    public Executer(ManualResetEventSlim pauseEvent)
    {
        _pauseEvent = pauseEvent;
    }

    public void ExecuteGraph()
    {
        while (/* your long-running condition */)
        {
            DoWorkStep();  

// simulate a random pause point
            if (_random.NextDouble() &amp;lt; 0.05)
            {
                Debug.WriteLine(&quot;…pausing now&quot;);
// put event into non-signaled (i.e. paused)
                _pauseEvent.Reset();
                _pauseEvent.Wait();  // block until resumed
                Debug.WriteLine(&quot;…resumed!&quot;);
            }
        }
    }

    private void DoWorkStep()
    {
        Thread.Sleep(200);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How It Works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;_pauseEvent&lt;/code&gt; starts in the signaled state, so &lt;code&gt;.Wait()&lt;/code&gt; returns immediately.&lt;/li&gt;
&lt;li&gt;Calling &lt;code&gt;_pauseEvent.Reset()&lt;/code&gt; switches it to non-signaled, so &lt;code&gt;.Wait()&lt;/code&gt; blocks the worker thread.&lt;/li&gt;
&lt;li&gt;When the UI calls &lt;code&gt;_pauseEvent.Set()&lt;/code&gt;, the blocked thread resumes execution.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;real-time-visual-updates&quot;&gt;Real-Time Visual Updates&lt;/h4&gt;
&lt;p&gt;A small challenge is real-time canvas updates - specifically, drawing a highlight box around the active node:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cc9wlvr9yv9ak29w575x.png&quot; alt=&quot;Highlight Box&quot;&gt;&lt;/p&gt;
&lt;p&gt;We can use an &lt;strong&gt;adorner&lt;/strong&gt; for this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c#&quot;&gt;/// &amp;lt;summary&amp;gt;
/// Show a red highlight around the specified FrameworkElement for a set duration.
/// &amp;lt;/summary&amp;gt;
public static async void ShowSimpleHighlight(FrameworkElement target, double margin = 5, int duration = 3)
{
    if (target == null)
        return;

// Get the adorner layer for that target
    AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(target);
    if (adornerLayer == null)
        return;

// Create and add adorner to the layer
    HighlightAdorner highlightAdorner = new(target, margin);
    adornerLayer.Add(highlightAdorner);

// Remove it after a few seconds
    await Task.Delay(TimeSpan.FromSeconds(duration));
    adornerLayer.Remove(highlightAdorner);
}

public class HighlightAdorner : Adorner
{
    private readonly Pen _pen;
    private readonly double _margin;

    public HighlightAdorner(UIElement adornedElement, double margin = 5)
        : base(adornedElement)
    {
        _pen = new Pen(Brushes.Red, 2);
        _pen.Freeze();
        _margin = margin;
        IsHitTestVisible = false;
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        Rect adornedElementRect = new(AdornedElement.RenderSize);
        adornedElementRect.Inflate(_margin, _margin);
        drawingContext.DrawRectangle(null, _pen, adornedElementRect);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;what-s-next-&quot;&gt;What's Next?&lt;/h4&gt;
&lt;p&gt;All that's left is a proper debug window!&lt;/p&gt;
&lt;h3 id=&quot;summary-1&quot;&gt;Summary&lt;/h3&gt;
&lt;p&gt;A good framework truly goes a long way. I had confidence in bringing procedural debugging to Divooka from the moment procedural context was introduced, because it naturally fits into an interpretative execution model. All that's required is a bit of focused engineering.&lt;/p&gt;
&lt;p&gt;The more challenging part is the GUI - but WPF offers solid isolation via MVVM, data binding, and adorners.&lt;/p&gt;
&lt;p&gt;We're not dealing with setting actual breakpoints yet, but the current setup is flexible enough to support that when the time comes. Ultimately, a debug window will act as our lens into the runtime: inspecting node states, variable values, and control flow.&lt;/p&gt;
&lt;h3 id=&quot;references&quot;&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://wiki.methodox.io/en/Divooka/Language/Contexts&quot;&gt;Procedural vs Dataflow context&lt;/a&gt; in Divooka on the Methodox Wiki.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.epicgames.com/documentation/en-us/unreal-engine/blueprint-debugging-example-in-unreal-engine&quot;&gt;Blueprint debugging in Unreal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Procedural debugging documentation on &lt;a rel=&quot;nofollow&quot; href=&quot;https://wiki.methodox.io/en/Divooka/Basic/ProceduralDebugging&quot;&gt;Methodox Wiki&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Divooka</category>
<guid isPermaLink="true">https://coderlegion.com/3830/devlog-20250708-procedural-context-visual-debugger-in-divooka</guid>
<pubDate>Tue, 08 Jul 2025 12:19:17 +0000</pubDate>
</item>
</channel>
</rss>