uCalc API Version: 2.1.3-preview.2 Released: 6/16/2026

Warning

uCalc API Preview Release Notice:The documentation describes the intended behavior of the API. The current preview build contains incomplete features, unoptimized performance, and is subject to breaking changes.

NextOverload

Method

Product: 

Transformer Library

Class: 

Rule

Retrieves the next rule in a sequence of rules that share the same starting pattern anchor, allowing for traversal of the overload chain.

Syntax

NextOverload()

Parameters

[None]

Return

Rule

Returns the next Rule object in the overload chain. If there are no more overloads, it returns an empty Rule for which NotEmpty() is false.

Remarks

🚶‍♂️ Traversing Rule Precedence with NextOverload

The NextOverload method provides a way to traverse the chain of Rules that share the same starting anchor text. When multiple rules are defined with patterns that could match at the same position, they form an implicit, stack-like list based on their definition order. This method acts as an iterator to walk through that list.

⚙️ Core Concept: The Overload Chain (LIFO)

Think of rules with the same anchor as a linked list where the head is the most recently defined rule:

  1. Head of the List: Retrieving a rule (e.g., from FromTo()) gives you the most recently defined rule for that pattern—the head of the chain.
  2. Walking the Chain: Calling .NextOverload() on that rule returns the previously defined rule that shares the same starting anchor.
  3. End of the Chain: When no more rules with that name exist, NextOverload() returns an empty Rule object. You can check for this termination condition using NotEmpty() or IsProperty(ItemIs::NotFound).

This mechanism is essential for introspection and for understanding the precedence of transformation rules.

🎯 Primary Use Cases

  • Inspecting FromTo Rule Precedence: The most common use case is to programmatically discover all defined rules that compete for the same starting text and verify their order of application. The LIFO (Last-In, First-Out) order means the rule returned by NextOverload has a lower priority than the one it was called on.
  • Debugging Complex Transformations: When a transformation isn't behaving as expected, you can use this method to walk the chain of rules associated with a problematic anchor to see which one is being applied and which ones are being overshadowed.

💡 Why uCalc? (Comparative Analysis)

This feature provides a significant advantage over traditional regular expression engines.

  • vs. Regex Alternation (|): In regex, precedence is determined by the left-to-right order within an alternation group (e.g., (cat|catch)). This is static and cannot be inspected or modified at runtime. uCalc's model is dynamic; rules can be added at any time, and NextOverload provides a programmatic way to inspect the resulting precedence chain.

  • vs. Function Overloading: In compiled languages like C# or C++, function overloading is a compile-time concept. The compiler selects the correct method, and there is no built-in mechanism to programmatically iterate through all available overloads at runtime. NextOverload gives uCalc powerful runtime introspection capabilities, a feature more common in highly dynamic languages.

Examples

Demonstrates the basic LIFO (Last-In, First-Out) behavior of NextOverload with two simple rules.
				
					using uCalcSoftware;

var uc = new uCalc();
var t = new uCalc.Transformer();
t.Text = "This is a test.";

// Rule 1 (defined first, lower priority)
var rule1 = t.FromTo("is", "[IS_1]");

// Rule 2 (defined second, higher priority)
var rule2 = t.FromTo("is", "[IS_2]");

Console.WriteLine("--- Applying transform (Rule 2 has precedence) ---");
Console.WriteLine(t.Transform());
Console.WriteLine("");

Console.WriteLine("--- Using NextOverload ---");
// Get the rule that comes after rule2
var nextRule = rule2.NextOverload();

Console.WriteLine($"Rule 2 pattern: {rule2.Pattern}");
Console.WriteLine($"Next rule's pattern: {nextRule.Pattern}");

// Verify that the next rule is indeed rule1
Console.WriteLine($"Next rule is rule1: {nextRule.Handle() == rule1.Handle()}");
				
			
--- Applying transform (Rule 2 has precedence) ---
This [IS_2] a test.

--- Using NextOverload ---
Rule 2 pattern: is
Next rule's pattern: is
Next rule is rule1: True
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

#define tf(IsTrue) ((IsTrue) ? "True" : "False")

int main() {
   uCalc uc;
   uCalc::Transformer t;
   t.Text("This is a test.");

   // Rule 1 (defined first, lower priority)
   auto rule1 = t.FromTo("is", "[IS_1]");

   // Rule 2 (defined second, higher priority)
   auto rule2 = t.FromTo("is", "[IS_2]");

   cout << "--- Applying transform (Rule 2 has precedence) ---" << endl;
   cout << t.Transform() << endl;
   cout << "" << endl;

   cout << "--- Using NextOverload ---" << endl;
   // Get the rule that comes after rule2
   auto nextRule = rule2.NextOverload();

   cout << "Rule 2 pattern: " << rule2.Pattern() << endl;
   cout << "Next rule's pattern: " << nextRule.Pattern() << endl;

   // Verify that the next rule is indeed rule1
   cout << "Next rule is rule1: " << tf(nextRule.Handle() == rule1.Handle()) << endl;
}
				
			
--- Applying transform (Rule 2 has precedence) ---
This [IS_2] a test.

--- Using NextOverload ---
Rule 2 pattern: is
Next rule's pattern: is
Next rule is rule1: True
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t As New uCalc.Transformer()
      t.Text = "This is a test."
      
      '// Rule 1 (defined first, lower priority)
      Dim rule1 = t.FromTo("is", "[IS_1]")
      
      '// Rule 2 (defined second, higher priority)
      Dim rule2 = t.FromTo("is", "[IS_2]")
      
      Console.WriteLine("--- Applying transform (Rule 2 has precedence) ---")
      Console.WriteLine(t.Transform())
      Console.WriteLine("")
      
      Console.WriteLine("--- Using NextOverload ---")
      '// Get the rule that comes after rule2
      Dim nextRule = rule2.NextOverload()
      
      Console.WriteLine($"Rule 2 pattern: {rule2.Pattern}")
      Console.WriteLine($"Next rule's pattern: {nextRule.Pattern}")
      
      '// Verify that the next rule is indeed rule1
      Console.WriteLine($"Next rule is rule1: {nextRule.Handle() = rule1.Handle()}")
   End Sub
End Module
				
			
--- Applying transform (Rule 2 has precedence) ---
This [IS_2] a test.

--- Using NextOverload ---
Rule 2 pattern: is
Next rule's pattern: is
Next rule is rule1: True
Iterates through a chain of rules with the same anchor to inspect their different replacement patterns.
				
					using uCalcSoftware;

var uc = new uCalc();
var t = new uCalc.Transformer();

// Define multiple rules with the same anchor ("Log:")
t.FromTo("Log: {msg}", "DEFAULT: {msg}");
t.FromTo("Log: ERROR {msg}", "CRITICAL: {msg}");
var lastRule = t.FromTo("Log: INFO {msg}", "INFO: {msg}"); // This has the highest priority

Console.WriteLine("--- Overload Chain for 'Log:' anchor ---");
var currentRule = lastRule;
do {
   Console.WriteLine($"Pattern: '{currentRule.Pattern}' -> Replacement: '{currentRule.Replacement}'");
   currentRule = currentRule.NextOverload();
} while (currentRule.NotEmpty());
				
			
--- Overload Chain for 'Log:' anchor ---
Pattern: 'Log: INFO {msg}' -> Replacement: 'INFO: {msg}'
Pattern: 'Log: ERROR {msg}' -> Replacement: 'CRITICAL: {msg}'
Pattern: 'Log: {msg}' -> Replacement: 'DEFAULT: {msg}'
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   uCalc::Transformer t;

   // Define multiple rules with the same anchor ("Log:")
   t.FromTo("Log: {msg}", "DEFAULT: {msg}");
   t.FromTo("Log: ERROR {msg}", "CRITICAL: {msg}");
   auto lastRule = t.FromTo("Log: INFO {msg}", "INFO: {msg}"); // This has the highest priority

   cout << "--- Overload Chain for 'Log:' anchor ---" << endl;
   auto currentRule = lastRule;
   do {
      cout << "Pattern: '" << currentRule.Pattern() << "' -> Replacement: '" << currentRule.Replacement() << "'" << endl;
      currentRule = currentRule.NextOverload();
   } while (currentRule.NotEmpty());
}
				
			
--- Overload Chain for 'Log:' anchor ---
Pattern: 'Log: INFO {msg}' -> Replacement: 'INFO: {msg}'
Pattern: 'Log: ERROR {msg}' -> Replacement: 'CRITICAL: {msg}'
Pattern: 'Log: {msg}' -> Replacement: 'DEFAULT: {msg}'
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t As New uCalc.Transformer()
      
      '// Define multiple rules with the same anchor ("Log:")
      t.FromTo("Log: {msg}", "DEFAULT: {msg}")
      t.FromTo("Log: ERROR {msg}", "CRITICAL: {msg}")
      Dim lastRule = t.FromTo("Log: INFO {msg}", "INFO: {msg}") '// This has the highest priority
      
      Console.WriteLine("--- Overload Chain for 'Log:' anchor ---")
      Dim currentRule = lastRule
      Do
         Console.WriteLine($"Pattern: '{currentRule.Pattern}' -> Replacement: '{currentRule.Replacement}'")
         currentRule = currentRule.NextOverload()
      Loop While currentRule.NotEmpty()
   End Sub
End Module
				
			
--- Overload Chain for 'Log:' anchor ---
Pattern: 'Log: INFO {msg}' -> Replacement: 'INFO: {msg}'
Pattern: 'Log: ERROR {msg}' -> Replacement: 'CRITICAL: {msg}'
Pattern: 'Log: {msg}' -> Replacement: 'DEFAULT: {msg}'
Internal Test: Verifies precedence and traversal of rules with different patterns but the same starting anchor ('Testing').
				
					using uCalcSoftware;

var uc = new uCalc();
var t = uc.NewTransformer();
t.Text = "Testing (a b c) Testing x y z! Testing 1 2 3.";

var Pattern1 = t.Pattern("Testing {etc}.").SetTag(111);
var Pattern2 = t.Pattern("Testing {etc}!").SetTag(222);
var Pattern3 = t.Pattern("Testing ({etc})").SetTag(333);

t.Find();
Console.WriteLine("--- Matches ---");
Console.WriteLine(t.Matches.Text);
Console.WriteLine("--- Patterns ---");
Console.WriteLine(Pattern1.Pattern);
Console.WriteLine(Pattern2.Pattern);
Console.WriteLine(Pattern3.Pattern);
Console.WriteLine("---- Tags ----");
Console.WriteLine(Pattern1.Tag);
Console.WriteLine(Pattern2.Tag);
Console.WriteLine(Pattern3.Tag);
Console.WriteLine("-- Overload Tags --");
// Note that most recently defined patterns come first
Console.WriteLine(Pattern3.NextOverload().Tag);
Console.WriteLine(Pattern2.NextOverload().Tag);
Console.WriteLine(Pattern1.NextOverload().Tag);
				
			
--- Matches ---
Testing (a b c)
Testing x y z!
Testing 1 2 3.
--- Patterns ---
Testing {etc}.
Testing {etc}!
Testing ({etc})
---- Tags ----
111
222
333
-- Overload Tags --
222
111
0
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   auto t = uc.NewTransformer();
   t.Text("Testing (a b c) Testing x y z! Testing 1 2 3.");

   auto Pattern1 = t.Pattern("Testing {etc}.").SetTag(111);
   auto Pattern2 = t.Pattern("Testing {etc}!").SetTag(222);
   auto Pattern3 = t.Pattern("Testing ({etc})").SetTag(333);

   t.Find();
   cout << "--- Matches ---" << endl;
   cout << t.Matches().Text() << endl;
   cout << "--- Patterns ---" << endl;
   cout << Pattern1.Pattern() << endl;
   cout << Pattern2.Pattern() << endl;
   cout << Pattern3.Pattern() << endl;
   cout << "---- Tags ----" << endl;
   cout << Pattern1.Tag() << endl;
   cout << Pattern2.Tag() << endl;
   cout << Pattern3.Tag() << endl;
   cout << "-- Overload Tags --" << endl;
   // Note that most recently defined patterns come first
   cout << Pattern3.NextOverload().Tag() << endl;
   cout << Pattern2.NextOverload().Tag() << endl;
   cout << Pattern1.NextOverload().Tag() << endl;
}
				
			
--- Matches ---
Testing (a b c)
Testing x y z!
Testing 1 2 3.
--- Patterns ---
Testing {etc}.
Testing {etc}!
Testing ({etc})
---- Tags ----
111
222
333
-- Overload Tags --
222
111
0
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t = uc.NewTransformer()
      t.Text = "Testing (a b c) Testing x y z! Testing 1 2 3."
      
      Dim Pattern1 = t.Pattern("Testing {etc}.").SetTag(111)
      Dim Pattern2 = t.Pattern("Testing {etc}!").SetTag(222)
      Dim Pattern3 = t.Pattern("Testing ({etc})").SetTag(333)
      
      t.Find()
      Console.WriteLine("--- Matches ---")
      Console.WriteLine(t.Matches.Text)
      Console.WriteLine("--- Patterns ---")
      Console.WriteLine(Pattern1.Pattern)
      Console.WriteLine(Pattern2.Pattern)
      Console.WriteLine(Pattern3.Pattern)
      Console.WriteLine("---- Tags ----")
      Console.WriteLine(Pattern1.Tag)
      Console.WriteLine(Pattern2.Tag)
      Console.WriteLine(Pattern3.Tag)
      Console.WriteLine("-- Overload Tags --")
      '// Note that most recently defined patterns come first
      Console.WriteLine(Pattern3.NextOverload().Tag)
      Console.WriteLine(Pattern2.NextOverload().Tag)
      Console.WriteLine(Pattern1.NextOverload().Tag)
   End Sub
End Module
				
			
--- Matches ---
Testing (a b c)
Testing x y z!
Testing 1 2 3.
--- Patterns ---
Testing {etc}.
Testing {etc}!
Testing ({etc})
---- Tags ----
111
222
333
-- Overload Tags --
222
111
0
Rule NextOverload and Tag
				
					using uCalcSoftware;

var uc = new uCalc();
var t = uc.NewTransformer();
t.Text = "Testing (a b c) Testing x y z! Testing 1 2 3.";

var Pattern1 = t.Pattern("Testing {etc}.").SetTag(111);
var Pattern2 = t.Pattern("Testing {etc}!").SetTag(222);
var Pattern3 = t.Pattern("Testing ({etc})").SetTag(333);

t.Find();
Console.WriteLine("--- Matches ---");
Console.WriteLine(t.Matches.Text);
Console.WriteLine("--- Patterns ---");
Console.WriteLine(Pattern1.Pattern);
Console.WriteLine(Pattern2.Pattern);
Console.WriteLine(Pattern3.Pattern);
Console.WriteLine("---- Tags ----");
Console.WriteLine(Pattern1.Tag);
Console.WriteLine(Pattern2.Tag);
Console.WriteLine(Pattern3.Tag);
Console.WriteLine("-- Overload Tags --");
// Note that most recently defined patterns come first
Console.WriteLine(Pattern3.NextOverload().Tag);
Console.WriteLine(Pattern2.NextOverload().Tag);
Console.WriteLine(Pattern1.NextOverload().Tag);


				
			
--- Matches ---
Testing (a b c)
Testing x y z!
Testing 1 2 3.
--- Patterns ---
Testing {etc}.
Testing {etc}!
Testing ({etc})
---- Tags ----
111
222
333
-- Overload Tags --
222
111
0
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   auto t = uc.NewTransformer();
   t.Text("Testing (a b c) Testing x y z! Testing 1 2 3.");

   auto Pattern1 = t.Pattern("Testing {etc}.").SetTag(111);
   auto Pattern2 = t.Pattern("Testing {etc}!").SetTag(222);
   auto Pattern3 = t.Pattern("Testing ({etc})").SetTag(333);

   t.Find();
   cout << "--- Matches ---" << endl;
   cout << t.Matches().Text() << endl;
   cout << "--- Patterns ---" << endl;
   cout << Pattern1.Pattern() << endl;
   cout << Pattern2.Pattern() << endl;
   cout << Pattern3.Pattern() << endl;
   cout << "---- Tags ----" << endl;
   cout << Pattern1.Tag() << endl;
   cout << Pattern2.Tag() << endl;
   cout << Pattern3.Tag() << endl;
   cout << "-- Overload Tags --" << endl;
   // Note that most recently defined patterns come first
   cout << Pattern3.NextOverload().Tag() << endl;
   cout << Pattern2.NextOverload().Tag() << endl;
   cout << Pattern1.NextOverload().Tag() << endl;


}
				
			
--- Matches ---
Testing (a b c)
Testing x y z!
Testing 1 2 3.
--- Patterns ---
Testing {etc}.
Testing {etc}!
Testing ({etc})
---- Tags ----
111
222
333
-- Overload Tags --
222
111
0
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t = uc.NewTransformer()
      t.Text = "Testing (a b c) Testing x y z! Testing 1 2 3."
      
      Dim Pattern1 = t.Pattern("Testing {etc}.").SetTag(111)
      Dim Pattern2 = t.Pattern("Testing {etc}!").SetTag(222)
      Dim Pattern3 = t.Pattern("Testing ({etc})").SetTag(333)
      
      t.Find()
      Console.WriteLine("--- Matches ---")
      Console.WriteLine(t.Matches.Text)
      Console.WriteLine("--- Patterns ---")
      Console.WriteLine(Pattern1.Pattern)
      Console.WriteLine(Pattern2.Pattern)
      Console.WriteLine(Pattern3.Pattern)
      Console.WriteLine("---- Tags ----")
      Console.WriteLine(Pattern1.Tag)
      Console.WriteLine(Pattern2.Tag)
      Console.WriteLine(Pattern3.Tag)
      Console.WriteLine("-- Overload Tags --")
      '// Note that most recently defined patterns come first
      Console.WriteLine(Pattern3.NextOverload().Tag)
      Console.WriteLine(Pattern2.NextOverload().Tag)
      Console.WriteLine(Pattern1.NextOverload().Tag)
      
      
   End Sub
End Module
				
			
--- Matches ---
Testing (a b c)
Testing x y z!
Testing 1 2 3.
--- Patterns ---
Testing {etc}.
Testing {etc}!
Testing ({etc})
---- Tags ----
111
222
333
-- Overload Tags --
222
111
0