uC++ EHM

Static Propagation (Sequel)

Static propagation resolves the handler at compile time by looking up its name lexically at the call site. In the call/return table it’s case 1 — static call, static return — and the construct that implements it is called a sequel.

Why introduce sequels when we already have labelled break for static multi-level exit?

Labelled break can’t modularize — if you want to break out of a nested control structure from inside a helper function, the label isn’t visible there. A sequel gives you a named static exit that any modularized code can call, while still resolving lexically and returning to the end of the declaring block. You get static-exit efficiency without being stuck in one function.

Shape

A sequel is a routine with no return value where:

  • the sequel name is looked up lexically at the call site, but
  • control returns to the end of the block in which the sequel is declared.
for ( ;; ) {
    sequel S1( ... ) { ... }            // nested handler
    void M1( ... ) { ... if ( ... ) S1( ... ); ... }   // calls sequel
    for ( ;; ) {
        sequel S2( ... ) { ... }
        C: for ( ;; ) {
            M1( ... );                  // modularized exit via S1
            if ( ... ) S2( ... );       // modularized exit via S2
            if ( ... ) break C;
        }
    } // S2 static return — control resumes here
} // S1 static return — control resumes here

Properties

  • Propagation follows the lexical structure.
  • Adheres to the termination model — the stack is unwound back to the declaring block.
  • Handler is statically known (like labelled break), so it can be as efficient as a direct transfer.
  • Handles termination for a non-recoverable event (simple exception handling).

Limitation

Sequels only work for monolithic programs — they must be statically nested at the point of use.

  • Fails for modular/library code because the static context of the module and the user code are disjoint.
  • If stack is separately compiled, the sequel call in push no longer knows the static blocks containing calls to it.

That’s exactly what motivates dynamic propagation — dynamic raise + dynamic lookup works across compilation units.