See this too.

I have found it difficult to describe throw-catch semantics from the perspective of CPS (Continuation Passing Style). It now occurs to me that throw-catch may be explained away along these lines: The following stuff is a very incomplete description of exception semantics but tries to express just the part that may be new.

To fix terminology I recapitulate some of CPS. We remove call and return from the execution model. We add back in “goto with arguments” and also “labels with parameters”. What was a call becomes a goto to the head of the old procedure body but with one more argument which is a continuation. For conventional compilation the continuation is merely the stack pointer. For languages such as Scheme, JavaScript and ActionScript the continuation is probably on the heap. What was a return becomes a goto to the continuation, passing the returned value as the one argument taken by the continuation. Some languages compile better with this conceptual framework.

For languages with “try - catch” the continuation, which is conventionally a label, becomes a pair of labels, the first to be used upon return and the second upon a throw. A call site in a try block passes as the second part of the continuation, a pointer to the catch code, along with the necessary environment. Here is the try-catch pattern synthesized from Scheme’s primitives including the call-with-current-continuation. (The code proper)

The following is an older perhaps more complete proposal with slightly different terminology.

There is an implicit unnamable bundle of ports attached to the computation—the continuation. They correspond to the throwables, or better the places to which throwables may be thrown. The bundle has no name in the language just as the return continuation has no name in the normal explanation of call-return semantics from the CPS perspective. Just as a return statement invokes the implicit continuation, so does a throw invoke some element of the bundle. To execute a block (stuff between curly braces) invoke the statements within that block with the same continuation and bundle. To execute a try block invoke the statements within but with a bundle that is obtained by replacing some of the elements of the current bundle with front ends that lead to catch clauses that match those element bundles. The continuation used in the try block is also replaced by one that leads to the finally clause associated with the try block. To execute a call statement pass the current bundle and a new continuation which includes the current continuation.

Invoking either a continuation or element of the bundle causes the computation to lose access to both the continuation and the bundle because the program cannot name either in order to stash it away.

P.S. What would exceptions mean in Scheme where continuations are accessible to the program?

The Google search “CPS exceptions” shows many notes on this. I don’t have the time now to dig into them. I suspect my idea is not new. The Google search “CPS continuations” leads to this. If Google understood what it knows about we would all be superfluous. I think it all started with Landin’s paper: A GENERALIZATION OF JUMPS AND LABELS. See too this fun critique of call/cc.