g-rh@cca.UUCP (Richard Harter) (04/07/86)
Summary: I proposed a language consisting of labelled blocks (or loops) with an escape statement that left the labelled block via a labelled 'fragment' of code. It has been mentioned to me in correspondence that the PL/I condition handler can be used in this fashion. In article <> savage@ssc-vax.UUCP (Lowell Savage) writes: >.... >I beleve that Ada provides such a facility (with an "exit" statement >which can take arguments that are block names) only without the >FRAGMENT capability. If there is some set of code that needs to be >executed before the block is exited, then that code can come before >the exit statement. However, Ada also provides another mechanism >which I think can be used for complete purpose intended by Richard. >This is the exception mechanism. The FRAGMENT is now the statements >after the exception handler, and the "exit" or "escape" statement is >now the Ada "RAISE" statement which raises some exception known only >within that block of code. > I knew (having written PL/I code for several years) about PL/I ON conditions, but I am not acquainted with the similar mechanism in ADA. It sounds like the PL/I and Ada constructs are more or less functionally equivalent to what I was suggesting, but not quite. The question is, what happens to control after the exception handler is done. In PL/I it goes back to the point where the exception was raised -- the escape is handled separately with a goto. Thus: ...... if (problem) then raise(exception) ...... LBL: ...... exception_handler: ...... goto LBL This is probably necessary for exception handlers which typically either (a) fixup the problem and go back to where it came from or (b) wrench control from the normal control stack and skip up multiple levels, hopefully disposing of accumulated frames along the way. If I understand what Ada offers correctly, one has either the automatic block exit or the fragment (handler) but not both at the same time. I could (but wont) dig up my Ada books and check it out. Some more thoughts that occur to me in passing. The first is that I am not a fan of using labels to indicate the first statement after a block of code, which all GOTO based solutions end up using; I would prefer to have blocks labelled and have escape statements which leave the block. This is in direct analogy with 'return' statements from procedures; I can escape from any level of nesting within a procedure with a return statement -- I ought to be able to do the same thing with internally nested blocks. Come to think of it, the BLOCK construct I was proposing is similar to a nested procedure except that: (a) It is executed by falling through to it; (b) It is not invoked by name; (c) It is parameterless. [Here is a construct that gives me the willies when I think about it: a return statement that lets you specify what routine you are returning from! An escape statement that lets you escape from a block at a higher level than the one you are in does this, but the legitmacy of the escape can be checked at compile time.] Another thought is that the whole problem of exception handling is a mess. C's setjmp/longjmp mechanism is no more than a "here is a low level primitive for the job -- you figure out how to do it yourself" approach. The PL/I ON condition handlers are only a small cut above C. It seems to me that the whole area of error handling is in need of major theoretical analysis. Richard Harter, SMDS Inc.
rossiter@svax.cs.cornell.edu (David G. Rossiter) (04/09/86)
Richard Harter writes: > > Another thought is that the whole problem of exception >handling is a mess. C's setjmp/longjmp mechanism is no more than >a "here is a low level primitive for the job -- you figure out >how to do it yourself" approach. The PL/I ON condition handlers >are only a small cut above C. It seems to me that the whole area >of error handling is in need of major theoretical analysis. > > Richard Harter, SMDS Inc. There is an *excellent* theoretical and practical analysis of error handling in a recent PhD thesis by Andrew P. Black, from Balliol College of Oxford University, UK. The title is "Exception Handling: the case against", submitted January 1982. Black is now at Univ. of Washington, I believe. I have a copy of the thesis which I obtained from the chairman of my PhD committee; I'm not sure where it is publically available. One could presumably email to Black. Anyway, he examines in detail exception handling mechanisms in producation languages like PL/I, Algol W, Algol 68, Mesa, and Ada, as well as in academic (but implemented) languages like CLU. He concludes that the way to think of so-called "exceptions" is as named constituents of a discriminated union data type (sort of like Pascal variant records, but type secure). It's very clean semantically and seems easy to program in and write compilers for. If there's more interest I can post the abstract and summary. David Rossiter / CS Dep't / Cornell University / Ithaca / NY / 14850 / USA {uw-beaver,ihnp4,decvax,vax135}!cornell!rossiter (UUCP) rossiter@gvax.cs.cornell.edu (ARPAnet) ; rossiter@CRNLCS (BITNET)
cdshaw@watdragon.UUCP (Chris Shaw) (04/13/86)
The most beautiful way I have seen for directed escape is with the Waterloo System Language's (WSL) GUESS-ADMIT structure. The following details are probably wrong, but you will hopefully get the gist: GUESS : LABEL1 quif( some_condition ) : LABEL1 /* quit guess completely*/ quif( some_other_cond ) /* goto admit */ < processing > ADMIT : LABEL2 /* label optional */ < different processing > ENDGUESS "quif( cond )" means quit the local block if "cond" is true. If a label follows in the quit statement, then the quif goes to the label. One can only go to labels (I recall) at your control statement level or "outer". For example, you can't quit into the body of a non-enclosing WHILE statement. The semantics of quits and quifs are basically gotos which can only branch DOWNWARDS. Therefore, no spaghetti code. This also makes for object code efficiency, since there is rarely a case where one would have to do complicated control structures. The GUESS-ADMIT structure is more or less a thinking person's case statement. ADMITs can be added at will in a GUESS statement. Thus the following could happen (code omitted between each GUESS or ADMIT): GUESS ADMIT :LABEL1 ADMIT :LABEL2 ADMIT :LABEL3 ENDGUESS Each ADMIT block handles one particular situation and no other. One can easily tell by looking what is being done, and it is clear at a glance where control passes to when processing for any ADMIT block is complete. The ADMIT labels allow for quitting past ADMIT blocks that will fail anyway. Hopefully I haven't been too unclear here, but the point I'm trying to make is this: GOTOs are "evil" because they are generally unconstrained in their "scope". The quif/quit structure answers this difficulty by allowing limited scope to where they can transfer control. All control function can be determined at compile time, and the maximum scope available is the surrounding procedure. (I used (and liked) this language a longish while ago. email me for more detail) Chris Shaw watmath!watrose!cdshaw or cdshaw@watmath University of Waterloo Bogus as HELL !!!
richw@ada-uts (04/18/86)
Another VERY good paper on the subject of exception handling: "A Modular Verifiable Exception-Handling Mechanism" by Shaula Yemini and Daniel M. Berry in ACM's TOPLAS (Transactions on Programming Languages and Systems), April 1985, Vol. 7., No. 2. This paper includes a very intelligent comparison of the exception handling mechanisms of several languages (most notably, CLU and Ada). Rich Wagner P.S. That TOPLAS issue also happens to include an article by William Weihl and Barbara Liskov (Prof. Liskov was the primary designer of CLU) entitled "Implementation of Resilient, Atomic Data Types".