VOID Language exceptions & runtime control flow

Structured exceptions.
Structured cleanup.

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

Control flow stays explicit even when execution fails.

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.

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.

Throw & catch

throw expression;, typed catches, catch variables, catch-all handlers, and derived-to-base handler ordering are supported through normal semantic validation.

Propagation & GC unwinding

Exceptions propagate across call frames while unwinding restores managed-root checkpoints and preserves the thrown exception object for the selected handler.

Finally semantics

finally runs on normal completion and exceptional exits. Required cleanup is not skipped when control leaves a protected region.

Structured exits

return, break, and continue cross one or more finally regions through the same structured cleanup machinery.

Nested handlers & rethrow

Nested try/catch/finally regions compose normally. Bare throw; rethrows the active exception while preserving its identity.

Iterator integration

Thrown exceptions, handler regions, cleanup, and managed roots remain valid across iterator suspension/resume and yield-generated state machines.

Delegates & events

Delegate, multicast-delegate, and event invocation propagate exceptions through the ordinary call/unwinding model while preserving managed targets.

Native & library boundaries

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.

Recovery-safe type initialization

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

Familiar syntax, compiler-owned lifetime.

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.

Typed catch + finally
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();
}
Nested rethrow
try
{
    try
    {
        RunStep();
    }
    catch (GameException)
    {
        LogFailure();
        throw;
    }
}
catch (Exception error)
{
    Console.WriteLine(error.Message);
}
Structured exit through finally
public static int FindScore(int[] scores)
{
    try
    {
        foreach (int score in scores)
        {
            if (score > 100)
                return score;
        }

        return -1;
    }
    finally
    {
        Console.WriteLine("search finished");
    }
}