Internal Test: An advanced example that adds logging to each transaction to trace the balance changes, showing how DSLs can be combined with custom functions.
ID: 1332
using uCalcSoftware;
var uc = new uCalc();
static void LogBalance(uCalc.Callback cb) {
// Get the message and the current balance to log
var msg = cb.ArgStr(1);
var bal = cb.uCalc.Eval("balance");
Console.WriteLine($"[LOG] {msg} | New Balance: {bal}");
}
// 1. Initialize the balance and the logger function
uc.DefineVariable("balance = 0");
uc.DefineFunction("LOG(msg As String)", LogBalance);
// 2. Define DSL rules that also call the LOG function
var t = uc.ExpressionTransformer;
// Each rule now has a side effect: logging its action.
t.FromTo("DEPOSIT {@Number:amount}",
"balance = balance + {amount}; LOG('Deposited {amount}')");
t.FromTo("WITHDRAW {@Number:amount}",
"balance = balance - {amount}; LOG('Withdrew {amount}')");
// 3. A longer script to test the log
var script = """
DEPOSIT 500
WITHDRAW 100
DEPOSIT 250
WITHDRAW 75
""";
Console.WriteLine("--- Transaction Log ---");
uc.EvalStr(script);
Console.WriteLine("-----------------------");
Console.WriteLine($"Final Balance: {uc.Eval("balance")}");
--- Transaction Log ---
[LOG] Deposited 500 | New Balance: 500
[LOG] Withdrew 100 | New Balance: 400
[LOG] Deposited 250 | New Balance: 650
[LOG] Withdrew 75 | New Balance: 575
-----------------------
Final Balance: 575 using uCalcSoftware; var uc = new uCalc(); static void LogBalance(uCalc.Callback cb) { // Get the message and the current balance to log var msg = cb.ArgStr(1); var bal = cb.uCalc.Eval("balance"); Console.WriteLine($"[LOG] {msg} | New Balance: {bal}"); } // 1. Initialize the balance and the logger function uc.DefineVariable("balance = 0"); uc.DefineFunction("LOG(msg As String)", LogBalance); // 2. Define DSL rules that also call the LOG function var t = uc.ExpressionTransformer; // Each rule now has a side effect: logging its action. t.FromTo("DEPOSIT {@Number:amount}", "balance = balance + {amount}; LOG('Deposited {amount}')"); t.FromTo("WITHDRAW {@Number:amount}", "balance = balance - {amount}; LOG('Withdrew {amount}')"); // 3. A longer script to test the log var script = """ DEPOSIT 500 WITHDRAW 100 DEPOSIT 250 WITHDRAW 75 """; Console.WriteLine("--- Transaction Log ---"); uc.EvalStr(script); Console.WriteLine("-----------------------"); Console.WriteLine($"Final Balance: {uc.Eval("balance")}");
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
void ucalc_call LogBalance(uCalcBase::Callback cb) {
// Get the message and the current balance to log
auto msg = cb.ArgStr(1);
auto bal = cb.uCalc().Eval("balance");
cout << "[LOG] " << msg << " | New Balance: " << bal << endl;
}
int main() {
uCalc uc;
// 1. Initialize the balance and the logger function
uc.DefineVariable("balance = 0");
uc.DefineFunction("LOG(msg As String)", LogBalance);
// 2. Define DSL rules that also call the LOG function
auto t = uc.ExpressionTransformer();
// Each rule now has a side effect: logging its action.
t.FromTo("DEPOSIT {@Number:amount}",
"balance = balance + {amount}; LOG('Deposited {amount}')");
t.FromTo("WITHDRAW {@Number:amount}",
"balance = balance - {amount}; LOG('Withdrew {amount}')");
// 3. A longer script to test the log
auto script = R"(
DEPOSIT 500
WITHDRAW 100
DEPOSIT 250
WITHDRAW 75
)";
cout << "--- Transaction Log ---" << endl;
uc.EvalStr(script);
cout << "-----------------------" << endl;
cout << "Final Balance: " << uc.Eval("balance") << endl;
}
--- Transaction Log ---
[LOG] Deposited 500 | New Balance: 500
[LOG] Withdrew 100 | New Balance: 400
[LOG] Deposited 250 | New Balance: 650
[LOG] Withdrew 75 | New Balance: 575
-----------------------
Final Balance: 575 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; void ucalc_call LogBalance(uCalcBase::Callback cb) { // Get the message and the current balance to log auto msg = cb.ArgStr(1); auto bal = cb.uCalc().Eval("balance"); cout << "[LOG] " << msg << " | New Balance: " << bal << endl; } int main() { uCalc uc; // 1. Initialize the balance and the logger function uc.DefineVariable("balance = 0"); uc.DefineFunction("LOG(msg As String)", LogBalance); // 2. Define DSL rules that also call the LOG function auto t = uc.ExpressionTransformer(); // Each rule now has a side effect: logging its action. t.FromTo("DEPOSIT {@Number:amount}", "balance = balance + {amount}; LOG('Deposited {amount}')"); t.FromTo("WITHDRAW {@Number:amount}", "balance = balance - {amount}; LOG('Withdrew {amount}')"); // 3. A longer script to test the log auto script = R"( DEPOSIT 500 WITHDRAW 100 DEPOSIT 250 WITHDRAW 75 )"; cout << "--- Transaction Log ---" << endl; uc.EvalStr(script); cout << "-----------------------" << endl; cout << "Final Balance: " << uc.Eval("balance") << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub LogBalance(ByVal cb As uCalc.Callback)
'// Get the message and the current balance to log
Dim msg = cb.ArgStr(1)
Dim bal = cb.uCalc.Eval("balance")
Console.WriteLine($"[LOG] {msg} | New Balance: {bal}")
End Sub
Public Sub Main()
Dim uc As New uCalc()
'// 1. Initialize the balance and the logger function
uc.DefineVariable("balance = 0")
uc.DefineFunction("LOG(msg As String)", AddressOf LogBalance)
'// 2. Define DSL rules that also call the LOG function
Dim t = uc.ExpressionTransformer
'// Each rule now has a side effect: logging its action.
t.FromTo("DEPOSIT {@Number:amount}",
"balance = balance + {amount}; LOG('Deposited {amount}')")
t.FromTo("WITHDRAW {@Number:amount}",
"balance = balance - {amount}; LOG('Withdrew {amount}')")
'// 3. A longer script to test the log
Dim script = "
DEPOSIT 500
WITHDRAW 100
DEPOSIT 250
WITHDRAW 75
"
Console.WriteLine("--- Transaction Log ---")
uc.EvalStr(script)
Console.WriteLine("-----------------------")
Console.WriteLine($"Final Balance: {uc.Eval("balance")}")
End Sub
End Module
--- Transaction Log ---
[LOG] Deposited 500 | New Balance: 500
[LOG] Withdrew 100 | New Balance: 400
[LOG] Deposited 250 | New Balance: 650
[LOG] Withdrew 75 | New Balance: 575
-----------------------
Final Balance: 575 Imports System Imports uCalcSoftware Public Module Program Public Sub LogBalance(ByVal cb As uCalc.Callback) '// Get the message and the current balance to log Dim msg = cb.ArgStr(1) Dim bal = cb.uCalc.Eval("balance") Console.WriteLine($"[LOG] {msg} | New Balance: {bal}") End Sub Public Sub Main() Dim uc As New uCalc() '// 1. Initialize the balance and the logger function uc.DefineVariable("balance = 0") uc.DefineFunction("LOG(msg As String)", AddressOf LogBalance) '// 2. Define DSL rules that also call the LOG function Dim t = uc.ExpressionTransformer '// Each rule now has a side effect: logging its action. t.FromTo("DEPOSIT {@Number:amount}", "balance = balance + {amount}; LOG('Deposited {amount}')") t.FromTo("WITHDRAW {@Number:amount}", "balance = balance - {amount}; LOG('Withdrew {amount}')") '// 3. A longer script to test the log Dim script = " DEPOSIT 500 WITHDRAW 100 DEPOSIT 250 WITHDRAW 75 " Console.WriteLine("--- Transaction Log ---") uc.EvalStr(script) Console.WriteLine("-----------------------") Console.WriteLine($"Final Balance: {uc.Eval("balance")}") End Sub End Module