Managed exception objects
The standard Exception class is an ordinary managed type with default/message constructors, inheritance, runtime type identity, and GC tracing. User exceptions derive from it normally.
VOID Language exceptions & runtime control flow
VOID now has a managed exception hierarchy, typed and catch-all handlers, cross-call propagation, GC-safe unwinding, finally semantics, rethrow, and integration across iterators, delegates, events, native/library boundaries, and static initialization.
Completed exception foundation
Exceptions were built as a runtime/control-flow subsystem rather than a parser-only feature. Throwing, handler selection, unwinding, GC root restoration, cleanup, suspended iterators, and boundary behavior share the same compiler-owned control-flow model.
The standard Exception class is an ordinary managed type with default/message constructors, inheritance, runtime type identity, and GC tracing. User exceptions derive from it normally.
throw expression;, typed catches, catch variables, catch-all handlers, and derived-to-base handler ordering are supported through normal semantic validation.
Exceptions propagate across call frames while unwinding restores managed-root checkpoints and preserves the thrown exception object for the selected handler.
finally runs on normal completion and exceptional exits. Required cleanup is not skipped when control leaves a protected region.
return, break, and continue cross one or more finally regions through the same structured cleanup machinery.
Nested try/catch/finally regions compose normally. Bare throw; rethrows the active exception while preserving its identity.
Thrown exceptions, handler regions, cleanup, and managed roots remain valid across iterator suspension/resume and yield-generated state machines.
Delegate, multicast-delegate, and event invocation propagate exceptions through the ordinary call/unwinding model while preserving managed targets.
Exception behavior is defined at native and reusable-library boundaries instead of allowing uncontrolled raw unwinding through C ABI frames. Boundary misuse receives focused diagnostics.
If static initialization throws, VOID restores the type-initialization state and GC-root checkpoint before rethrowing, allowing later use to retry through a clean runtime state.
Representative syntax
The surface looks familiar, but the important work is below it: handler discovery, propagation, root restoration, finally execution, rethrow identity, and integration with generated iterator state all remain part of one native runtime/control-flow implementation.
public sealed class GameException : Exception
{
public GameException(string message) : base(message)
{
}
}
try
{
throw new GameException("bad state");
}
catch (GameException error)
{
Console.WriteLine(error.Message);
}
finally
{
Cleanup();
}
try
{
try
{
RunStep();
}
catch (GameException)
{
LogFailure();
throw;
}
}
catch (Exception error)
{
Console.WriteLine(error.Message);
}
public static int FindScore(int[] scores)
{
try
{
foreach (int score in scores)
{
if (score > 100)
return score;
}
return -1;
}
finally
{
Console.WriteLine("search finished");
}
}