Dynamic Propagation
Dynamic propagation resolves the handler at runtime β the raise walks the call stack looking for a matching guarded block. It covers cases 3 and 4 of the call/return table:
| return \ raise | static call | dynamic call |
|---|---|---|
| static | 1) sequel | 3) termination exception |
| dynamic | 2) routine | 4) routine pointer, virtual routine, resumption |
Why pay for dynamic lookup when sequels are cheaper?
Because dynamic propagation works for separately-compiled programs β a library can raise an exception without knowing who will catch it. The cost is that the handler isnβt statically known, so the same raise-site action runs for every exceptional control-flow change. Thatβs the tradeoff: lose compile-time knowledge, gain modularity.
Termination (case 3)
Dynamic raise, static return β also called dynamic multi-level exit (DME).
- Control transfers from the raise to the handler β dynamic raise (call).
- When the handler returns, it performs a static return β stack is unwound (like sequel).
- See Termination.
Resumption (case 4)
Dynamic raise, dynamic return.
- Control transfers from raise to handler β dynamic raise (call).
- Handler returns dynamically β stack is NOT unwound (like a routine).
- See Resumption.
Why dynamic is the default for library code
Sequels fail when stack is separately compiled because the sequel call in push no longer knows the static blocks containing calls to it. Dynamic propagation sidesteps this entirely β the raise site names only the exception type, and the runtime finds the first matching handler on the stack.