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.
Error handling and control flow
Product:Â
Class:Â
Explains uCalc's state-based error handling and its mechanisms for creating custom control-flow structures.
Remarks
💣 Error Handling & Control Flow: A Different Approach
uCalc's architecture for handling errors and implementing control flow differs from what developers in traditional compiled languages like C# or C++ might expect. Instead of relying on language-level try/catch blocks and if/for statements, uCalc provides an integrated, engine-level system designed for the dynamic nature of a parsing environment. This approach prioritizes performance, flexibility, and, most importantly, the ability to recover from errors gracefully.
This topic covers the two pillars of this system: uCalc's state-based error model and its lazy-evaluation mechanism for building custom control structures.
1. Error Handling: Recover, Don't Just Fail
In a parsing context, especially one dealing with user input, errors are not "exceptional" events; they are a normal part of operation. A user might type an incomplete formula or misspell a variable name. A traditional try/catch block, which unwinds the call stack, is a heavyweight solution for such common occurrences. uCalc uses a more lightweight, state-based model.
The Two Methods of Error Handling
A. Reactive: Checking the Error State
The simplest way to handle errors is to check the engine's state after an operation. Every uCalc instance has an Error property that holds information about the last error. If an operation like EvalStr fails, it doesn't throw an exception; it returns an error message as a string and sets the error state.
var result = uc.EvalStr("5 * (10 +"); // Invalid syntax// Reactively check if an error occurredif (uc.Error.Code != ErrorCode.None) {{ Console.WriteLine($"An error occurred: {uc.Error.Message}");}This approach is simple and effective for many use cases, but you only learn about the error after the operation has already aborted.
B. Proactive: The Error Handler Callback
For more advanced control, you can register an error handler using AddHandler. This is a callback function that uCalc invokes the moment an error occurs, giving you the power to intercept, inspect, and even recover from it.
The Power of Recovery with Resume
The most powerful feature of an error handler is the ability to control what happens next by setting the Error.Response property. While the default is to Abort, you can set it to ErrorHandlerResponse::Resume.
This instructs the engine to continue execution as if the error never happened. This is the key to building fault-tolerant and "intelligent" parsers. For example, an error handler can catch an Undefined_Identifier error, automatically define the missing variable, and then Resume the evaluation, which will now succeed. This is a level of dynamic recovery that is very difficult to achieve with standard try/catch blocks.
For a full tutorial, see Handling Errors.
2. Control Flow: Lazy Evaluation with ByExpr
Just as uCalc avoids language-level try/catch, it also provides its own mechanism for control flow structures like if statements and loops. This is necessary because of a fundamental concept in expression evaluation: eager evaluation.
The Problem with Eager Evaluation
In most languages, when you call a function like MyFunc(arg1, arg2), both arg1 and arg2 are fully calculated before MyFunc begins to run. This makes it impossible to create a custom if function. A call like MyIf(1 > 0, 100, 1/0) would crash because the 1/0 in the "else" branch is evaluated eagerly, even though it should never be executed.
The Solution: ByExpr
uCalc solves this with the ByExpr parameter modifier. When used in a function signature, it tells the engine not to pass the argument's final value, but to pass an unevaluated Expression object instead.
The callback function then has complete control over this Expression object. It can:
- Evaluate it: Call
.Evaluate()to get its result. - Ignore it: Choose not to evaluate it at all (the key to short-circuiting).
- Evaluate it multiple times: The foundation for creating custom loops.
This mechanism is the core of all control flow in uCalc. It is used to implement the built-in IIf function (a ternary operator), as well as looping constructs like ForLoop and DoLoop. It also empowers you to build your own custom control structures, elevating uCalc from a simple calculator to a lightweight scripting engine.
For a detailed guide, see Lazy Evaluation (ByExpr).
Examples
Checking the error code for a simple syntax error
using uCalcSoftware;
var uc = new uCalc();
var result = uc.Eval("MyVar * 10");
Console.WriteLine("An error has occurred!");
Console.WriteLine($"Error #: {(int)uc.Error.Code}");
Console.WriteLine($"Error Message: {uc.Error.Message}");
Console.WriteLine($"Error Location: {uc.Error.Location}");
Console.WriteLine($"Error Expression: {uc.Error.Expression}");
An error has occurred!
Error #: 258
Error Message: Undefined identifier
Error Location: 0
Error Expression: MyVar * 10 using uCalcSoftware; var uc = new uCalc(); var result = uc.Eval("MyVar * 10"); Console.WriteLine("An error has occurred!"); Console.WriteLine($"Error #: {(int)uc.Error.Code}"); Console.WriteLine($"Error Message: {uc.Error.Message}"); Console.WriteLine($"Error Location: {uc.Error.Location}"); Console.WriteLine($"Error Expression: {uc.Error.Expression}");
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
auto result = uc.Eval("MyVar * 10");
cout << "An error has occurred!" << endl;
cout << "Error #: " << (int)uc.Error().Code() << endl;
cout << "Error Message: " << uc.Error().Message() << endl;
cout << "Error Location: " << uc.Error().Location() << endl;
cout << "Error Expression: " << uc.Error().Expression() << endl;
}
An error has occurred!
Error #: 258
Error Message: Undefined identifier
Error Location: 0
Error Expression: MyVar * 10 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; auto result = uc.Eval("MyVar * 10"); cout << "An error has occurred!" << endl; cout << "Error #: " << (int)uc.Error().Code() << endl; cout << "Error Message: " << uc.Error().Message() << endl; cout << "Error Location: " << uc.Error().Location() << endl; cout << "Error Expression: " << uc.Error().Expression() << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
Dim result = uc.Eval("MyVar * 10")
Console.WriteLine("An error has occurred!")
Console.WriteLine($"Error #: {CInt(uc.Error.Code)}")
Console.WriteLine($"Error Message: {uc.Error.Message}")
Console.WriteLine($"Error Location: {uc.Error.Location}")
Console.WriteLine($"Error Expression: {uc.Error.Expression}")
End Sub
End Module
An error has occurred!
Error #: 258
Error Message: Undefined identifier
Error Location: 0
Error Expression: MyVar * 10 Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() Dim result = uc.Eval("MyVar * 10") Console.WriteLine("An error has occurred!") Console.WriteLine($"Error #: {CInt(uc.Error.Code)}") Console.WriteLine($"Error Message: {uc.Error.Message}") Console.WriteLine($"Error Location: {uc.Error.Location}") Console.WriteLine($"Error Expression: {uc.Error.Expression}") End Sub End Module
A practical example demonstrating all four related floating-point error configuration methods.
using uCalcSoftware;
var uc = new uCalc();
Console.WriteLine($"Divide by Zero (Default): {uc.EvalStr("1/0")}");
uc.Error.TrapOnDivideByZero = true;
Console.WriteLine($"Divide by Zero (Error Enabled): {uc.EvalStr("1/0")}");
Console.WriteLine("");
Console.WriteLine($"Invalid Operation (Default): {uc.EvalStr("Sqrt(-1)")}");
uc.Error.TrapOnInvalid = true;
Console.WriteLine($"Invalid Operation (Error Enabled): {uc.EvalStr("Sqrt(-1)")}");
Console.WriteLine("");
Console.WriteLine($"Overflow (Default): {uc.EvalStr("5*10^308")}");
uc.Error.TrapOnOverflow = true;
Console.WriteLine($"Overflow (Error Enabled): {uc.EvalStr("5*10^308")}");
Console.WriteLine("");
Console.WriteLine($"Underflow (Default): {uc.EvalStr("10^-308/10000")}");
uc.Error.TrapOnUnderflow = true;
Console.WriteLine($"Underflow (Error Enabled): {uc.EvalStr("10^-308/10000")}");
Divide by Zero (Default): inf
Divide by Zero (Error Enabled): Division by 0
Invalid Operation (Default): nan
Invalid Operation (Error Enabled): Invalid operation
Overflow (Default): inf
Overflow (Error Enabled): Floating point overflow
Underflow (Default): 0
Underflow (Error Enabled): Floating point underflow using uCalcSoftware; var uc = new uCalc(); Console.WriteLine($"Divide by Zero (Default): {uc.EvalStr("1/0")}"); uc.Error.TrapOnDivideByZero = true; Console.WriteLine($"Divide by Zero (Error Enabled): {uc.EvalStr("1/0")}"); Console.WriteLine(""); Console.WriteLine($"Invalid Operation (Default): {uc.EvalStr("Sqrt(-1)")}"); uc.Error.TrapOnInvalid = true; Console.WriteLine($"Invalid Operation (Error Enabled): {uc.EvalStr("Sqrt(-1)")}"); Console.WriteLine(""); Console.WriteLine($"Overflow (Default): {uc.EvalStr("5*10^308")}"); uc.Error.TrapOnOverflow = true; Console.WriteLine($"Overflow (Error Enabled): {uc.EvalStr("5*10^308")}"); Console.WriteLine(""); Console.WriteLine($"Underflow (Default): {uc.EvalStr("10^-308/10000")}"); uc.Error.TrapOnUnderflow = true; Console.WriteLine($"Underflow (Error Enabled): {uc.EvalStr("10^-308/10000")}");
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
cout << "Divide by Zero (Default): " << uc.EvalStr("1/0") << endl;
uc.Error().TrapOnDivideByZero(true);
cout << "Divide by Zero (Error Enabled): " << uc.EvalStr("1/0") << endl;
cout << "" << endl;
cout << "Invalid Operation (Default): " << uc.EvalStr("Sqrt(-1)") << endl;
uc.Error().TrapOnInvalid(true);
cout << "Invalid Operation (Error Enabled): " << uc.EvalStr("Sqrt(-1)") << endl;
cout << "" << endl;
cout << "Overflow (Default): " << uc.EvalStr("5*10^308") << endl;
uc.Error().TrapOnOverflow(true);
cout << "Overflow (Error Enabled): " << uc.EvalStr("5*10^308") << endl;
cout << "" << endl;
cout << "Underflow (Default): " << uc.EvalStr("10^-308/10000") << endl;
uc.Error().TrapOnUnderflow(true);
cout << "Underflow (Error Enabled): " << uc.EvalStr("10^-308/10000") << endl;
}
Divide by Zero (Default): inf
Divide by Zero (Error Enabled): Division by 0
Invalid Operation (Default): nan
Invalid Operation (Error Enabled): Invalid operation
Overflow (Default): inf
Overflow (Error Enabled): Floating point overflow
Underflow (Default): 0
Underflow (Error Enabled): Floating point underflow #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; cout << "Divide by Zero (Default): " << uc.EvalStr("1/0") << endl; uc.Error().TrapOnDivideByZero(true); cout << "Divide by Zero (Error Enabled): " << uc.EvalStr("1/0") << endl; cout << "" << endl; cout << "Invalid Operation (Default): " << uc.EvalStr("Sqrt(-1)") << endl; uc.Error().TrapOnInvalid(true); cout << "Invalid Operation (Error Enabled): " << uc.EvalStr("Sqrt(-1)") << endl; cout << "" << endl; cout << "Overflow (Default): " << uc.EvalStr("5*10^308") << endl; uc.Error().TrapOnOverflow(true); cout << "Overflow (Error Enabled): " << uc.EvalStr("5*10^308") << endl; cout << "" << endl; cout << "Underflow (Default): " << uc.EvalStr("10^-308/10000") << endl; uc.Error().TrapOnUnderflow(true); cout << "Underflow (Error Enabled): " << uc.EvalStr("10^-308/10000") << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
Console.WriteLine($"Divide by Zero (Default): {uc.EvalStr("1/0")}")
uc.Error.TrapOnDivideByZero = true
Console.WriteLine($"Divide by Zero (Error Enabled): {uc.EvalStr("1/0")}")
Console.WriteLine("")
Console.WriteLine($"Invalid Operation (Default): {uc.EvalStr("Sqrt(-1)")}")
uc.Error.TrapOnInvalid = true
Console.WriteLine($"Invalid Operation (Error Enabled): {uc.EvalStr("Sqrt(-1)")}")
Console.WriteLine("")
Console.WriteLine($"Overflow (Default): {uc.EvalStr("5*10^308")}")
uc.Error.TrapOnOverflow = true
Console.WriteLine($"Overflow (Error Enabled): {uc.EvalStr("5*10^308")}")
Console.WriteLine("")
Console.WriteLine($"Underflow (Default): {uc.EvalStr("10^-308/10000")}")
uc.Error.TrapOnUnderflow = true
Console.WriteLine($"Underflow (Error Enabled): {uc.EvalStr("10^-308/10000")}")
End Sub
End Module
Divide by Zero (Default): inf
Divide by Zero (Error Enabled): Division by 0
Invalid Operation (Default): nan
Invalid Operation (Error Enabled): Invalid operation
Overflow (Default): inf
Overflow (Error Enabled): Floating point overflow
Underflow (Default): 0
Underflow (Error Enabled): Floating point underflow Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() Console.WriteLine($"Divide by Zero (Default): {uc.EvalStr("1/0")}") uc.Error.TrapOnDivideByZero = true Console.WriteLine($"Divide by Zero (Error Enabled): {uc.EvalStr("1/0")}") Console.WriteLine("") Console.WriteLine($"Invalid Operation (Default): {uc.EvalStr("Sqrt(-1)")}") uc.Error.TrapOnInvalid = true Console.WriteLine($"Invalid Operation (Error Enabled): {uc.EvalStr("Sqrt(-1)")}") Console.WriteLine("") Console.WriteLine($"Overflow (Default): {uc.EvalStr("5*10^308")}") uc.Error.TrapOnOverflow = true Console.WriteLine($"Overflow (Error Enabled): {uc.EvalStr("5*10^308")}") Console.WriteLine("") Console.WriteLine($"Underflow (Default): {uc.EvalStr("10^-308/10000")}") uc.Error.TrapOnUnderflow = true Console.WriteLine($"Underflow (Error Enabled): {uc.EvalStr("10^-308/10000")}") End Sub End Module
Adding an error handler callback
using uCalcSoftware;
var uc = new uCalc();
static void MyErrorHandler(Handle_uCalc h) {
var uc = new uCalc(h);
Console.WriteLine("An error has occurred!");
Console.WriteLine($"Error #: {(int)uc.Error.Code}");
Console.WriteLine($"Error Message: {uc.Error.Message}");
Console.WriteLine($"Error Symbol: {uc.Error.Symbol}");
Console.WriteLine($"Error Location: {uc.Error.Location}");
Console.WriteLine($"Error Expression: {uc.Error.Expression}");
}
uc.Error.AddHandler(MyErrorHandler);
Console.WriteLine(uc.EvalStr("123+"));
Console.WriteLine("");
uc.Error.TrapOnDivideByZero = true;
Console.WriteLine(uc.EvalStr("5/0"));
An error has occurred!
Error #: 257
Error Message: Syntax error
Error Symbol: +
Error Location: 3
Error Expression: 123+
Syntax error
An error has occurred!
Error #: 8
Error Message: Division by 0
Error Symbol:
Error Location: 0
Error Expression:
Division by 0 using uCalcSoftware; var uc = new uCalc(); static void MyErrorHandler(Handle_uCalc h) { var uc = new uCalc(h); Console.WriteLine("An error has occurred!"); Console.WriteLine($"Error #: {(int)uc.Error.Code}"); Console.WriteLine($"Error Message: {uc.Error.Message}"); Console.WriteLine($"Error Symbol: {uc.Error.Symbol}"); Console.WriteLine($"Error Location: {uc.Error.Location}"); Console.WriteLine($"Error Expression: {uc.Error.Expression}"); } uc.Error.AddHandler(MyErrorHandler); Console.WriteLine(uc.EvalStr("123+")); Console.WriteLine(""); uc.Error.TrapOnDivideByZero = true; Console.WriteLine(uc.EvalStr("5/0"));
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
void ucalc_call MyErrorHandler(Handle_uCalc h) {
auto uc = uCalc(h);
cout << "An error has occurred!" << endl;
cout << "Error #: " << (int)uc.Error().Code() << endl;
cout << "Error Message: " << uc.Error().Message() << endl;
cout << "Error Symbol: " << uc.Error().Symbol() << endl;
cout << "Error Location: " << uc.Error().Location() << endl;
cout << "Error Expression: " << uc.Error().Expression() << endl;
}
int main() {
uCalc uc;
uc.Error().AddHandler(MyErrorHandler);
cout << uc.EvalStr("123+") << endl;
cout << "" << endl;
uc.Error().TrapOnDivideByZero(true);
cout << uc.EvalStr("5/0") << endl;
}
An error has occurred!
Error #: 257
Error Message: Syntax error
Error Symbol: +
Error Location: 3
Error Expression: 123+
Syntax error
An error has occurred!
Error #: 8
Error Message: Division by 0
Error Symbol:
Error Location: 0
Error Expression:
Division by 0 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; void ucalc_call MyErrorHandler(Handle_uCalc h) { auto uc = uCalc(h); cout << "An error has occurred!" << endl; cout << "Error #: " << (int)uc.Error().Code() << endl; cout << "Error Message: " << uc.Error().Message() << endl; cout << "Error Symbol: " << uc.Error().Symbol() << endl; cout << "Error Location: " << uc.Error().Location() << endl; cout << "Error Expression: " << uc.Error().Expression() << endl; } int main() { uCalc uc; uc.Error().AddHandler(MyErrorHandler); cout << uc.EvalStr("123+") << endl; cout << "" << endl; uc.Error().TrapOnDivideByZero(true); cout << uc.EvalStr("5/0") << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub MyErrorHandler(ByVal h As Handle_uCalc)
Dim uc As New uCalc(h)
Console.WriteLine("An error has occurred!")
Console.WriteLine($"Error #: {CInt(uc.Error.Code)}")
Console.WriteLine($"Error Message: {uc.Error.Message}")
Console.WriteLine($"Error Symbol: {uc.Error.Symbol}")
Console.WriteLine($"Error Location: {uc.Error.Location}")
Console.WriteLine($"Error Expression: {uc.Error.Expression}")
End Sub
Public Sub Main()
Dim uc As New uCalc()
uc.Error.AddHandler(AddressOf MyErrorHandler)
Console.WriteLine(uc.EvalStr("123+"))
Console.WriteLine("")
uc.Error.TrapOnDivideByZero = true
Console.WriteLine(uc.EvalStr("5/0"))
End Sub
End Module
An error has occurred!
Error #: 257
Error Message: Syntax error
Error Symbol: +
Error Location: 3
Error Expression: 123+
Syntax error
An error has occurred!
Error #: 8
Error Message: Division by 0
Error Symbol:
Error Location: 0
Error Expression:
Division by 0 Imports System Imports uCalcSoftware Public Module Program Public Sub MyErrorHandler(ByVal h As Handle_uCalc) Dim uc As New uCalc(h) Console.WriteLine("An error has occurred!") Console.WriteLine($"Error #: {CInt(uc.Error.Code)}") Console.WriteLine($"Error Message: {uc.Error.Message}") Console.WriteLine($"Error Symbol: {uc.Error.Symbol}") Console.WriteLine($"Error Location: {uc.Error.Location}") Console.WriteLine($"Error Expression: {uc.Error.Expression}") End Sub Public Sub Main() Dim uc As New uCalc() uc.Error.AddHandler(AddressOf MyErrorHandler) Console.WriteLine(uc.EvalStr("123+")) Console.WriteLine("") uc.Error.TrapOnDivideByZero = true Console.WriteLine(uc.EvalStr("5/0")) End Sub End Module
Creating an error handler that automatically defines variables on the fly by checking for an 'Undefined Identifier' error.
using uCalcSoftware;
var uc = new uCalc();
static void AutoDefineHandler(Handle_uCalc h) {
var uc = new uCalc(h);
// Check if the error is specifically an undefined identifier
if (uc.Error.Code == ErrorCode.Undefined_Identifier) {
// If so, define the missing variable and instruct uCalc to resume
Console.WriteLine($"Auto-defining variable: '{uc.Error.Symbol}'");
uc.DefineVariable(uc.Error.Symbol);
uc.Error.Response = ErrorHandlerResponse.Resume;
}
}
uc.Error.AddHandler(AutoDefineHandler);
// 'x' doesn't exist, but the handler will intercept the error and create it.
var Result = uc.EvalStr("x = 10; x * 5");
Console.WriteLine($"Result: {Result}");
Auto-defining variable: 'x'
Result: 50 using uCalcSoftware; var uc = new uCalc(); static void AutoDefineHandler(Handle_uCalc h) { var uc = new uCalc(h); // Check if the error is specifically an undefined identifier if (uc.Error.Code == ErrorCode.Undefined_Identifier) { // If so, define the missing variable and instruct uCalc to resume Console.WriteLine($"Auto-defining variable: '{uc.Error.Symbol}'"); uc.DefineVariable(uc.Error.Symbol); uc.Error.Response = ErrorHandlerResponse.Resume; } } uc.Error.AddHandler(AutoDefineHandler); // 'x' doesn't exist, but the handler will intercept the error and create it. var Result = uc.EvalStr("x = 10; x * 5"); Console.WriteLine($"Result: {Result}");
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
void ucalc_call AutoDefineHandler(Handle_uCalc h) {
auto uc = uCalc(h);
// Check if the error is specifically an undefined identifier
if (uc.Error().Code() == ErrorCode::Undefined_Identifier) {
// If so, define the missing variable and instruct uCalc to resume
cout << "Auto-defining variable: '" << uc.Error().Symbol() << "'" << endl;
uc.DefineVariable(uc.Error().Symbol());
uc.Error().Response(ErrorHandlerResponse::Resume);
}
}
int main() {
uCalc uc;
uc.Error().AddHandler(AutoDefineHandler);
// 'x' doesn't exist, but the handler will intercept the error and create it.
auto Result = uc.EvalStr("x = 10; x * 5");
cout << "Result: " << Result << endl;
}
Auto-defining variable: 'x'
Result: 50 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; void ucalc_call AutoDefineHandler(Handle_uCalc h) { auto uc = uCalc(h); // Check if the error is specifically an undefined identifier if (uc.Error().Code() == ErrorCode::Undefined_Identifier) { // If so, define the missing variable and instruct uCalc to resume cout << "Auto-defining variable: '" << uc.Error().Symbol() << "'" << endl; uc.DefineVariable(uc.Error().Symbol()); uc.Error().Response(ErrorHandlerResponse::Resume); } } int main() { uCalc uc; uc.Error().AddHandler(AutoDefineHandler); // 'x' doesn't exist, but the handler will intercept the error and create it. auto Result = uc.EvalStr("x = 10; x * 5"); cout << "Result: " << Result << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub AutoDefineHandler(ByVal h As Handle_uCalc)
Dim uc As New uCalc(h)
'// Check if the error is specifically an undefined identifier
If uc.Error.Code = ErrorCode.Undefined_Identifier Then
'// If so, define the missing variable and instruct uCalc to resume
Console.WriteLine($"Auto-defining variable: '{uc.Error.Symbol}'")
uc.DefineVariable(uc.Error.Symbol)
uc.Error.Response = ErrorHandlerResponse.Resume
End If
End Sub
Public Sub Main()
Dim uc As New uCalc()
uc.Error.AddHandler(AddressOf AutoDefineHandler)
'// 'x' doesn't exist, but the handler will intercept the error and create it.
Dim Result = uc.EvalStr("x = 10; x * 5")
Console.WriteLine($"Result: {Result}")
End Sub
End Module
Auto-defining variable: 'x'
Result: 50 Imports System Imports uCalcSoftware Public Module Program Public Sub AutoDefineHandler(ByVal h As Handle_uCalc) Dim uc As New uCalc(h) '// Check if the error is specifically an undefined identifier If uc.Error.Code = ErrorCode.Undefined_Identifier Then '// If so, define the missing variable and instruct uCalc to resume Console.WriteLine($"Auto-defining variable: '{uc.Error.Symbol}'") uc.DefineVariable(uc.Error.Symbol) uc.Error.Response = ErrorHandlerResponse.Resume End If End Sub Public Sub Main() Dim uc As New uCalc() uc.Error.AddHandler(AddressOf AutoDefineHandler) '// 'x' doesn't exist, but the handler will intercept the error and create it. Dim Result = uc.EvalStr("x = 10; x * 5") Console.WriteLine($"Result: {Result}") End Sub End Module
Error handler order
using uCalcSoftware;
var uc = new uCalc();
static void ErrorHandlerA(Handle_uCalc h) {
var uc = new uCalc(h);
Console.WriteLine("Handler A called");
}
static void ErrorHandlerB(Handle_uCalc h) {
var uc = new uCalc(h);
Console.WriteLine("Handler B called");
}
static void ErrorHandlerC(Handle_uCalc h) {
var uc = new uCalc(h);
Console.WriteLine("Handler C called");
}
static void ErrorHandlerD(Handle_uCalc h) {
var uc = new uCalc(h);
Console.WriteLine("Handler D called");
}
static void ErrorHandlerE(Handle_uCalc h) {
var uc = new uCalc(h);
Console.WriteLine("Handler E called");
}
uc.Error.AddHandler(ErrorHandlerA);
uc.Error.AddHandler(ErrorHandlerB);
uc.Error.AddHandler(ErrorHandlerC);
uc.Error.AddHandler(ErrorHandlerD, -1);
uc.Error.AddHandler(ErrorHandlerE, 3);
Console.WriteLine(uc.EvalStr("10 / "));
Handler C called
Handler B called
Handler A called
Handler E called
Handler D called
Syntax error using uCalcSoftware; var uc = new uCalc(); static void ErrorHandlerA(Handle_uCalc h) { var uc = new uCalc(h); Console.WriteLine("Handler A called"); } static void ErrorHandlerB(Handle_uCalc h) { var uc = new uCalc(h); Console.WriteLine("Handler B called"); } static void ErrorHandlerC(Handle_uCalc h) { var uc = new uCalc(h); Console.WriteLine("Handler C called"); } static void ErrorHandlerD(Handle_uCalc h) { var uc = new uCalc(h); Console.WriteLine("Handler D called"); } static void ErrorHandlerE(Handle_uCalc h) { var uc = new uCalc(h); Console.WriteLine("Handler E called"); } uc.Error.AddHandler(ErrorHandlerA); uc.Error.AddHandler(ErrorHandlerB); uc.Error.AddHandler(ErrorHandlerC); uc.Error.AddHandler(ErrorHandlerD, -1); uc.Error.AddHandler(ErrorHandlerE, 3); Console.WriteLine(uc.EvalStr("10 / "));
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
void ucalc_call ErrorHandlerA(Handle_uCalc h) {
auto uc = uCalc(h);
cout << "Handler A called" << endl;
}
void ucalc_call ErrorHandlerB(Handle_uCalc h) {
auto uc = uCalc(h);
cout << "Handler B called" << endl;
}
void ucalc_call ErrorHandlerC(Handle_uCalc h) {
auto uc = uCalc(h);
cout << "Handler C called" << endl;
}
void ucalc_call ErrorHandlerD(Handle_uCalc h) {
auto uc = uCalc(h);
cout << "Handler D called" << endl;
}
void ucalc_call ErrorHandlerE(Handle_uCalc h) {
auto uc = uCalc(h);
cout << "Handler E called" << endl;
}
int main() {
uCalc uc;
uc.Error().AddHandler(ErrorHandlerA);
uc.Error().AddHandler(ErrorHandlerB);
uc.Error().AddHandler(ErrorHandlerC);
uc.Error().AddHandler(ErrorHandlerD, -1);
uc.Error().AddHandler(ErrorHandlerE, 3);
cout << uc.EvalStr("10 / ") << endl;
}
Handler C called
Handler B called
Handler A called
Handler E called
Handler D called
Syntax error #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; void ucalc_call ErrorHandlerA(Handle_uCalc h) { auto uc = uCalc(h); cout << "Handler A called" << endl; } void ucalc_call ErrorHandlerB(Handle_uCalc h) { auto uc = uCalc(h); cout << "Handler B called" << endl; } void ucalc_call ErrorHandlerC(Handle_uCalc h) { auto uc = uCalc(h); cout << "Handler C called" << endl; } void ucalc_call ErrorHandlerD(Handle_uCalc h) { auto uc = uCalc(h); cout << "Handler D called" << endl; } void ucalc_call ErrorHandlerE(Handle_uCalc h) { auto uc = uCalc(h); cout << "Handler E called" << endl; } int main() { uCalc uc; uc.Error().AddHandler(ErrorHandlerA); uc.Error().AddHandler(ErrorHandlerB); uc.Error().AddHandler(ErrorHandlerC); uc.Error().AddHandler(ErrorHandlerD, -1); uc.Error().AddHandler(ErrorHandlerE, 3); cout << uc.EvalStr("10 / ") << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub ErrorHandlerA(ByVal h As Handle_uCalc)
Dim uc As New uCalc(h)
Console.WriteLine("Handler A called")
End Sub
Public Sub ErrorHandlerB(ByVal h As Handle_uCalc)
Dim uc As New uCalc(h)
Console.WriteLine("Handler B called")
End Sub
Public Sub ErrorHandlerC(ByVal h As Handle_uCalc)
Dim uc As New uCalc(h)
Console.WriteLine("Handler C called")
End Sub
Public Sub ErrorHandlerD(ByVal h As Handle_uCalc)
Dim uc As New uCalc(h)
Console.WriteLine("Handler D called")
End Sub
Public Sub ErrorHandlerE(ByVal h As Handle_uCalc)
Dim uc As New uCalc(h)
Console.WriteLine("Handler E called")
End Sub
Public Sub Main()
Dim uc As New uCalc()
uc.Error.AddHandler(AddressOf ErrorHandlerA)
uc.Error.AddHandler(AddressOf ErrorHandlerB)
uc.Error.AddHandler(AddressOf ErrorHandlerC)
uc.Error.AddHandler(AddressOf ErrorHandlerD, -1)
uc.Error.AddHandler(AddressOf ErrorHandlerE, 3)
Console.WriteLine(uc.EvalStr("10 / "))
End Sub
End Module
Handler C called
Handler B called
Handler A called
Handler E called
Handler D called
Syntax error Imports System Imports uCalcSoftware Public Module Program Public Sub ErrorHandlerA(ByVal h As Handle_uCalc) Dim uc As New uCalc(h) Console.WriteLine("Handler A called") End Sub Public Sub ErrorHandlerB(ByVal h As Handle_uCalc) Dim uc As New uCalc(h) Console.WriteLine("Handler B called") End Sub Public Sub ErrorHandlerC(ByVal h As Handle_uCalc) Dim uc As New uCalc(h) Console.WriteLine("Handler C called") End Sub Public Sub ErrorHandlerD(ByVal h As Handle_uCalc) Dim uc As New uCalc(h) Console.WriteLine("Handler D called") End Sub Public Sub ErrorHandlerE(ByVal h As Handle_uCalc) Dim uc As New uCalc(h) Console.WriteLine("Handler E called") End Sub Public Sub Main() Dim uc As New uCalc() uc.Error.AddHandler(AddressOf ErrorHandlerA) uc.Error.AddHandler(AddressOf ErrorHandlerB) uc.Error.AddHandler(AddressOf ErrorHandlerC) uc.Error.AddHandler(AddressOf ErrorHandlerD, -1) uc.Error.AddHandler(AddressOf ErrorHandlerE, 3) Console.WriteLine(uc.EvalStr("10 / ")) End Sub End Module
Raises an error with a dynamic message if a validation check fails within a callback.
using uCalcSoftware;
var uc = new uCalc();
static void ValidateValue(uCalc.Callback cb) {
var val = cb.Arg(1);
if (val > 100) {
// The error message includes the problematic value, making it dynamic.
cb.Error.Raise("Value exceeds maximum of 100. Got: " + val.ToString());
} else {
cb.Return(val);
}
}
uc.DefineFunction("CheckValue(val)", ValidateValue);
Console.WriteLine(uc.EvalStr("CheckValue(50)"));
Console.WriteLine(uc.EvalStr("CheckValue(123)"));
50
Value exceeds maximum of 100. Got: 123 using uCalcSoftware; var uc = new uCalc(); static void ValidateValue(uCalc.Callback cb) { var val = cb.Arg(1); if (val > 100) { // The error message includes the problematic value, making it dynamic. cb.Error.Raise("Value exceeds maximum of 100. Got: " + val.ToString()); } else { cb.Return(val); } } uc.DefineFunction("CheckValue(val)", ValidateValue); Console.WriteLine(uc.EvalStr("CheckValue(50)")); Console.WriteLine(uc.EvalStr("CheckValue(123)"));
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
void ucalc_call ValidateValue(uCalcBase::Callback cb) {
auto val = cb.Arg(1);
if (val > 100) {
// The error message includes the problematic value, making it dynamic.
cb.Error().Raise("Value exceeds maximum of 100. Got: " + to_string((int)val));
} else {
cb.Return(val);
}
}
int main() {
uCalc uc;
uc.DefineFunction("CheckValue(val)", ValidateValue);
cout << uc.EvalStr("CheckValue(50)") << endl;
cout << uc.EvalStr("CheckValue(123)") << endl;
}
50
Value exceeds maximum of 100. Got: 123 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; void ucalc_call ValidateValue(uCalcBase::Callback cb) { auto val = cb.Arg(1); if (val > 100) { // The error message includes the problematic value, making it dynamic. cb.Error().Raise("Value exceeds maximum of 100. Got: " + to_string((int)val)); } else { cb.Return(val); } } int main() { uCalc uc; uc.DefineFunction("CheckValue(val)", ValidateValue); cout << uc.EvalStr("CheckValue(50)") << endl; cout << uc.EvalStr("CheckValue(123)") << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub ValidateValue(ByVal cb As uCalc.Callback)
Dim val = cb.Arg(1)
If val > 100 Then
'// The error message includes the problematic value, making it dynamic.
cb.Error.Raise("Value exceeds maximum of 100. Got: " + val.ToString())
Else
cb.Return(val)
End If
End Sub
Public Sub Main()
Dim uc As New uCalc()
uc.DefineFunction("CheckValue(val)", AddressOf ValidateValue)
Console.WriteLine(uc.EvalStr("CheckValue(50)"))
Console.WriteLine(uc.EvalStr("CheckValue(123)"))
End Sub
End Module
50
Value exceeds maximum of 100. Got: 123 Imports System Imports uCalcSoftware Public Module Program Public Sub ValidateValue(ByVal cb As uCalc.Callback) Dim val = cb.Arg(1) If val > 100 Then '// The error message includes the problematic value, making it dynamic. cb.Error.Raise("Value exceeds maximum of 100. Got: " + val.ToString()) Else cb.Return(val) End If End Sub Public Sub Main() Dim uc As New uCalc() uc.DefineFunction("CheckValue(val)", AddressOf ValidateValue) Console.WriteLine(uc.EvalStr("CheckValue(50)")) Console.WriteLine(uc.EvalStr("CheckValue(123)")) End Sub End Module