[net.lang.mod2] exceptions

manis@UBC.CSNET (Vincent Manis) (02/04/86)

I'm personally strongly opposed to hardwiring exception handling into 
programming languages. In part, this is because one wants to discourage
routine use of exceptions for other than error handling; in part, because
one of the major virtues of Modula-2 is its small size.

Exceptions, by their very nature, are global. One signals an exception, and
any module in the system (or at least in the dynamic execution history of
the program) can catch them. As a result, two modules may have different
ideas on what to do with a given exception. Thus, there are very good 
program structuring arguments against extensive use of exceptions. 

What many people have missed is that Modula-2 gives the programmer ''local
exceptions'', in the form of procedure variables. Rather than exporting an
exception, a module may export a procedure variable (or a procedure which
accepts a procedure parameter). The client module can assign this variable a
value; when an exceptional condition occurs, the procedure is invoked, and
does whatever the client deems appropriate.

It should be noted that this possibility is not present in Ada(TM), as
procedure variables and procedural parameters are not provided (the Steelman
specification explicitly ruled them out; I never understood why).

There are, however, a number of situations in which exception handling (or
more precisely non-local jumps) are necessary. Jeffrey McArthur's proposals
are quite reasonable (though I'd prefer to represent exception names by
integers rather than character strings, for efficiency's sake). The C
setjmp/longjmp facility, which McArthur references, is quite good enough by
itself, though, and very easy to implement.

lsr@apple.UUCP (Larry Rosenstein) (02/13/86)

In article <913:manis@cs.ubc.cdn> writes:
>
>Exceptions, by their very nature, are global. One signals an exception, and
>any module in the system (or at least in the dynamic execution history of
>the program) can catch them. As a result, two modules may have different
>ideas on what to do with a given exception. Thus, there are very good 
>program structuring arguments against extensive use of exceptions. 
>

Not necessarily true.  

The CLU exception mechanism is local; if a procedure raises an exception,
only its caller can handle it.  If the caller does not handle it, the
exception is converted into a generic 'failure' exception, which will be
propagated up another level (and so on).  

The reason for this is modularity; a routine should not have to know about
exceptions that could be generated several levels of calls deep.  This is
in keeping with the CLU programming methodology that the internals of a
module are hidden from users of the module.  

The language provided a convenient way to pass an exception up a level, but
you had to explicitly write this.  Non-local exception mechanisms are
convenient because you do not have to explicitly pass exceptions on to your
caller if you don't care about them.

I have implemented a setjmp/longjmp kind of mechanism for the Pascal we use
(on top ofthe language), and found it to be very useful in handling errors.




-- 
Larry Rosenstein
Apple Computer

UUCP:  {voder, nsc, ios, mtxinu, dual}!apple!lsr
CSNET: lsr@Apple.CSNET

wyant@apollo.UUCP (Geoffrey Wyant) (04/22/86)

One problem I see with implementing exceptions outside the 
language comes in the following form:
                               
    VAR
        fileOpened: BOOLEAN ;

        Exceptions.SetHandler(status) ;

        IF status <> ok THEN
            IF fileOpened THEN
                FileSystem.Close(...);
            END ;
        END ;

        fileOpened := FALSE ;
        FileSystem.Open(...) ;
        fileOpened := TRUE ;

Now a smart optimizing complier will notice that
the first assignment to fileOpened is never used.
It then thinks that it is free to delete that
expression.  This is clearly wrong.  The fact is 
that either the compiler has to know about stack
unwinders (exception handling) or there must be
some way to declare that a variable is "volitale"
and the compiler not optimize assignments to it.
Similiar things can happen when dealing with IO
devices (don't want optimize away those control
register assignments !) Now I think that it's a
bad idea to stick exception handling into the
language, but the ability to specify attributes
in a declaration, such as "volatile" seems to me
to be usefull.  Then one could write the above
example as

    VAR
        fileOpened: [VOLITALE] BOOLEAN ;

    ....      

I think that the notion of attributes could be
generalized to allow specifying field sizes
for dealing with device registers:

    VAR
        mythicalCSR: [VOLITALE] RECORD
                        [BITS] commands: 
                               SET OF (go, halt, catchFire) ;
                        [BITS] status:   
                               SET OF (broken, flaming, toasting, running) ;
                    END (* record *);

What do other people think of this ?  I think it provides usefull
functionality without warping the language too much.


                Geoff Wyant
-------

bobc@tikal.UUCP (Bob Campbell) (05/01/86)

In article <8604240042.AA13982@uw-beaver.arpa> wyant@apollo.UUCP (Geoffrey Wyant) writes:
>
>register assignments !) Now I think that it's a
>bad idea to stick exception handling into the
>language, but the ability to specify attributes
>in a declaration, such as "volatile" seems to me
>to be usefull.  Then one could write the above
>example as
>
>    VAR
>        fileOpened: [VOLITALE] BOOLEAN ;
>    ....      
>
>I think that the notion of attributes could be
>generalized to allow specifying field sizes
>for dealing with device registers:
>
>    VAR
>        mythicalCSR: [VOLITALE] RECORD
>                        [BITS] commands: 
>                               SET OF (go, halt, catchFire) ;
>                        [BITS] status:   
>                               SET OF (broken, flaming, toasting, running) ;
>                    END (* record *);
>
>What do other people think of this ?  I think it provides usefull
>functionality without warping the language too much.
>
>
>                Geoff Wyant
>-------

Well what I think is that these should be handled as compiler options
ie:

VAR
    fileOpened: (*$VOLITALE*) BOOLEAN ;
....      

VAR
    mythicalCSR: (*$VOLITALE*) RECORD
                    (*$BITS*) commands: 
                           SET OF (go, halt, catchFire) ;
                    (*$BITS*) status:   
                           SET OF (broken, flaming, toasting, running) ;
                END (* record *);

At this point I must admit that I don't under stand what BITS means.
Does this mean size of BITSET or is BITS to be replaced by a number
indicating the size of the element.  (Is this Record to also be
packed? ie how many words it this record).  To continue and expand
functionality one would add the compiler option "PACKED".  Therefore a
one word of 16 bits records containing two bit fields (as above) would
become:

VAR
    mythicalCSR: (*$VOLITALE*) RECORD
	(*$PACKED*)
	(*$BITS:3*) commands:
	    SET OF (go, halt, catchFire);
	(*$BITS:4*) status:
	    SET OF (broken, flaming, toasting, running);
	END (* record *);

This interpretation of the original intent feels wrong to me as the
size of the SETS (and subranges etc.) and be determined by the number
of elements (or the size of the subrange) dummy feilds can be inserted
to fill out for unused bits.  (* Assuming that PACKED maximizes use of
bits in the record *)

This is my 2+ cents, 

Bob Campbell
{fluke,dataio,hplsla,sunup,uw-beaver}!tikal!bobc