EXTENSION OF THE EXCEPTION HANDLING MECHANISM M.L.Gassanenko St.Petersburg, Russia. gml@ag.pu.ru gml@agspbu.spb.su The proposed notation: TRY CATCH( \ or ['] CATCH )CATCH ?DUP IF \ or a CASE statement 3 RETRY \ make 3 aditional attempts \ (stacks get restored, control \ transfers after TRY) ( THROW ) \ invoke the next "higer" level \ of exception processing (optional) THEN \ There's no END-TRY TRY and CATCH use two different parts of the same frame on the exception stack. All exception stack allocations are done by CATCH( ... )CATCH ; TRY uses the attempt subframe of the attempt&exception frame. The rest of talk explains why this extension was needed, and why the standard ['] CATCH structure was considered infelicitous. ------------- Plan 1. Considering demands on human memory 2. Why a special control structure for repetition of attempts is preferrable. Why RETRY should restore stacks (i.e. be a non-local loop) 3. A criterion of aptness of a control structure, on which ['] ... CATCH fails 4. Obligatory factoring vs. optional factoring (criticism of ['] CATCH) 5. Conclusion -------------- 1. Considering demands on human memory The number of items that a human can contemporarily keep im mind is restricted by a psychological constant ( 7 +- 2 ). When a person has to keep more, he is likely to forget something. Looking for something forgotten also requires some attention (i.e. turns into additional human time and memory demands). This very much resembles counting registers when programming in Assembler: some data require N registers to be kept and M registers to be recalculated. Felicitous register allocation results in less time expenses. Our goal was to create a syntax for exception handling and attempts retrying with minimal demands on human memory. The less attention has to be given language constructs, (namely, to exception handling ones), the more attention may be focused on the problem, the faster the problem gets solved. --------------- 2. Why a special control structure for repetition of attempts is preferrable. Why RETRY should restore stacks (i.e. be a non-local loop) When we program actions that may fail, our problem naturally splits into two parts: the normal sequence of actions and the ways to return to the normal sequence if something happens. These two sorts of code appear in the same modules, but we do not want them to mix up. The use of a special control structure for making additional attempts enables us to distinguish these two types of code at a glance. It is easier to think of code that may fail as of actions that normally succeed. We write it as if it cannot fail and then add analysis of errors. RETRY that restores stacks is convenient here because it guarantees the stack balance and allows us not to think about it later. (Unbalanced stack due to an exception could be a nasty bug). ------------- 3. A criterion of aptness of a control structure A control structure should not require auxiliary objects, especially named auxiliary objects. A well-known example: ALGOL-68: | PASCAL: | BASIC, Assemblers: perfect |auxiliary blocks | auxiliary labels and GOTOs if ... | if ... | IF ... GOTO else1 then | then | ... | begin ... | ... else | end | GOTO endif1 ... | else | then1: fi | begin ... | ... | end | endif1: The rightmost construct occupies at least 4 items in human memory: there are two branch origins and two branch destinations. Each label occupies two items (one for definition and another for usage). --------------- 4. Obligatory factoring vs. optional factoring (criticism of ['] CATCH) The ANSI standard CATCH compels programmer to factor his code into at least two words: one for actions that may fail and another for initialisation, repetition of the actions, reaction on errors. This factoring looks sometimes quite arbitrary, since words for initialisation, reaction on errors and the actions often belong to the same level of knowledge. Example of meaningless factoring: : read-sector | : try-read-sector motors-?on | seek-track read-record TRY | ; CATCH( | : read-sector seek-track | motors-?on read-record | TRY )CATCH | ['] try-read-sector CATCH IF | IF recalibrate | recalibrate \ go to track 0 3 RETRY | 3 RETRY THROW | THROW THEN | THEN ; | ; The word TRY-READ-SECTOR is used only once, it cannot be executed from the keyboard because it requires masking some interrupts. The words SEEK-TRACK, READ-RECORD, RECALIBRATE, MOTORS-?ON reflect the same level of knowledge. There's no reason to put them into different definitions. The two definitions TRY-READ-SECTOR and READ-SECTOR constitute one and the same module, but this module is split into two parts. It is programmer who should decide how to factor his code. While obligatory factoring is a weakness of the standard CATCH syntax, it provides a solution for another weakness of the standard approach: if we use the same control structures (IFs and loops) to program both actions-that-may-fail and repetition of attemts, these two sorts of code mix up and the program becomes less readable. We solved this problem by introducing RETRY. -------- 5. Conclusion The main result of this work is the syntax for repetition of attempts, simple and easily distinguishable. The proposed notation is a compromise: it tries to compensate the standard CATCH weaknesses but does not radically differ from it. Like the standard CATCH, our construct does not restore the contents of stacks. This means that either cannot consume data left on the stack or the programmer has to add a stack contents restoration mechanism himself. In practice we used the first approach. We may expect that evolution of the Forth exception handling mehanism will continue.