ISSUE: Block Dynamic Environment REVISION HISTORY: 13 Sep 94, Rob MacLachlan [exit scope covers exceptions] 12 Sep 94, Rob MacLachlan STATUS: open RELATED ISSUES: At Most One Cleanup CATEGORY: change/clarification PROBLEM DESCRIPTION: The "block" statement is the primary statement which manipulates the dynamic environment (remember "let handler"), yet its effect on the dynamic environment is not clear. This is at least partly because there is no concept of a single dynamic environment; instead there is a piecemeal discussion of legal and illegal situations. Some statements are inconsistent with a unified dynamic environment (one-stack model.) In particular, p36 in the DIRM says: If one of the cleanup-clauses is terminated by a non-local exit out of the block, any following cleanup clauses in the same block are not executed. Most importantly, the semantics are simply very confusing, since it seems that each "cleanup" or "exception" clause is executed in a different dynamic environment (modified by the preceding or following clauses.) PROPOSAL: Change/clarify that a block establishes up to three distinguishable bindings in the dynamic environment: Cleanup clause Exit procedure Exception clauses These portions of the block statement are executed with the specified bindings in effect: Body: Exit procedure/Exception clauses/Cleanup clause Cleanup clause: Exit procedure/Exception clauses Exception clauses: Exit procedure All exception clauses are executed in the same dynamic environment (none of the handlers established in the block are visible during the execution of the exception clauses.) This can be thought of as parallel instantiation of the handler bindings. Although this scoping rule is probably sufficient to define the intended semantics, some passages in the DIRM implicitly contradict this interpretation and need to be changed or qualified to make the intent clear. In the paragraph on pp36-37: When an exit procedure is invoked [...] Finally, the cleanup clauses of the establishing block are executed, further invocation of the exit procedure becomes invalid [...] Add a new paragraph: Note that a block statement may also be the target of a non-local exit due to the execution of a handler clause. Before the exception clause is executed, intervening cleanup clauses are executed as described above (including any clause for the establishing block.) The exit procedure may be invoked during execution of exception clauses, in which case the argument values are immediately returned from the block (the cleanup clause already having been executed.) On page 160: Note that when the expressions in the Exception-Body are executed, the HANDLER established BY THAT EXCEPTION CLAUSE is no longer active. Amend to: Note that when the expressions in the Exception-Body are executed, all handlers established by the block are no longer active. There are also various mentions of multiple cleanup clauses that should be eliminated on pages 35-37 and 160. RATIONALE: Although the intent isn't started in the DIRM, it is fairly clear (from the provision for multiple cleanup clauses) that the dynamic environments of the cleanup/exception clauses were intended to interleave. If (as proposed) all cleanup clauses are executed in the same dynamic environment, then there would be no point in having more than one, so this proposal should be adopted along with "At Most One Cleanup". Note that with default parallel binding, sequential exception bindings can be easily (and readably) introduced by wrapping additional enclosing "block" statements, whereas if sequential were the the default, getting parallel semantics requires complex code using "let handler" and additional exit procedures. The ordering of the of the three dynamic bindings is intended to preserve as many as possible of the necessarily arbitrary rules mentioned in the DIRM: -- The exit surrounds all of the body since that seems to be strongly implied by binding the exit procedure at the start of the statement. -- The cleanup is inside the exception clauses since that seems most natural with the documented terminating semantics. The cleanup is part of terminating the body, not part of handling the exception. It isn't completely clear that the abstract concept of "dynamic environment" should be introduced in user documentation, but some sort of "stack + search" model should be documented, since it already implicit and is partially described in the conceptual matter at the front of the conditions chapter. See especially the discussion of "outside stack/middle stack/inside stack" on page 150. EXAMPLES: Consider: block (done) stuff; exception () HANDLER1; exception () HANDLER2; end; It appears that currently later exception clauses handle conditions signalled by earlier ones, so if HANDLER1 signals , then HANDLER2 would be invoked. In this proposal, all exception clauses are executed in the same environment, so some outer handler for would be run. With this proposal, the above block could be expanded into: block (done) block (internal-cond1) block (internal-cond2) let handler = method (cond) internal-cond2(cond); end method; let handler = method (cond) internal-cond1(cond); end method; done(stuff); end block; // internal-cond1 done(HANDLER1); end block; // internal-cond2 done(HANDLER2); end block; // done Note reversal of the "let handler" bindings to ensure that the first exception clause shadows the second. BENEFITS: Replaces an unbounded number of dynamic environments composed of two different kinds of bindings with at most three environments. This eliminates unnecessary complexity without loss of power. Several internal contradictions in the DIRM are also fixed.