[comp.lang.modula2] Exceptions

drc@cs.brown.edu (David R. Chase) (04/07/90)

I tend to the pro-exception camp, with reservations.  I've written and
debugged bits and pieces of Modula-3, and written a back-end for a M-3
compiler.  The 15-line-normal/50-line-exceptional example
notwithstanding, I have found exceptions to be useful, and I find them
useful because of the way they allow separation of "normal" from "not
normal" cases.  In some numerical code that I wrote, it was quite
handy to take care of "failed to converge" and "divide-by-zero" as
exceptional cases.  Exceptions also have one useful abuse -- locally,
they do a good job as "structured goto", and a compiler can easily
turn that into a goto and avoid the overhead of exception dispatch.

Exceptions are somewhat better than return codes for construction of
reliable programs, because (Modula-3 semantics) if your code fails to
catch a raised exception, then it blows up ("Uncaught exception --
core dumped").  This doesn't solve the whole problem --
testing/verification of code may still fail to ever raise an exception
that won't be caught -- but it's a lot better than nothing.  Plus, in
Modula-3 procedure signatures include declarations of what exceptions
will be raised -- a compiler can (and one does/did) warn of places
where an uncaught exception may occur.  

Now, the reservations.

There are holes in this, of course -- the default signature for
Modula-3 procedures is "RAISES ANY", which means that a sloppy
programmer will get little help from the compiler.  This was hotly
debated among the Modula-3 committee, and at least one paper was
produced arguing for a default of RAISES NONE.  Furthermore, a
TRY-EXCEPT-ELSE-END will catch everything, which may be a bit of
overkill.  There's stylistic problems too; at least one person has
argued that the default exception list for extensible packages ought
to be "RAISES ANY" because "who knows what exceptions will be
appropriate to the extensions?" and I don't really have a good
counter-argument.

Some future descendant of the language might steal a bit from the C++
proposals, and either allow some sort of "subtyping" of exceptions, or
go so far as to say that exceptions are just objects (i.e., a
declaration of what exceptions might be raised = a declaration of the
possible types that might be exceptionally returned).  This gives some
additional flexibility that might help avoid the use of RAISES ANY.
(DON'T look for this in anything called Modula-3; I'm not on the
committee, but I'm pretty sure of their behavior in this case.)

My biggest gripe concerning exceptions has nothing to do with their
typical use or language semantics.  It turns out that it is difficult
to *generate* efficient, reliable object code using either C as an
intermediate language or a C-based backend.  People from Xerox say
that it isn't too bad if you just wrap each guarded block into its own
nested procedure (simulated, of course, in C, with a great number of
pointers), but I don't have a great deal of confidence in that (i.e.,
I'd like to see a detailed and thorough comparison).  Setjmp+longjmp,
of course, is a flaky option, since that combination rarely combines
correct semantics and speed, and often possesses neither.

It's "just a SMOP" of build an optimizing backend safe for
Modula-3-style exceptions, but it hasn't happened yet.  The Acorn
Modula-2+ compiler generated quite acceptable code without any
significant optimizations, however, so maybe this isn't that large a
problem.  Do note that their M2+ compiler had its own back-end -- it
just did a good job of generating code.

David

lins@Apple.COM (Chuck Lins) (04/10/90)

In article <35384@brunix.UUCP> drc@cs.brown.edu (David R. Chase) writes:
[well a bunch of stuff deleted, you'll have to read them yourself]

Both Dan and David make good points. One alternative that hasn't been mentioned
yet is implementing a module for exception handling. Such a module requires
a bit of assembly language coding for the implementation but it can (and has)
been done. This is how MacApp(R) implements a signaling exception mechanism
in a language without exception handling features (Object Pascal). This
overhead at run-time is minimal. So you can have an efficient, exception
mechanism in a language without exceptions. BTW, the Metrowerks Modula-2
compiler for the Macintosh(TM) provides just such a module.


-- 
Chuck Lins               | "Exit left to funway."
Apple Computer, Inc.     | Internet: lins@apple.com
20525 Mariani Avenue     | AppleLink: LINS
Mail Stop 41-K           | 
Cupertino, CA 95014      | "Self-proclaimed Object Oberon Evangelist"
The intersection of Apple's ideas and my ideas yields the empty set.

hal@newton.physics.purdue.edu (Hal Chambers) (04/10/90)

In article <40148@apple.Apple.COM> lins@Apple.COM (Chuck Lins) writes:
>Both Dan and David make good points. One alternative that hasn't been mentioned
>yet is implementing a module for exception handling...
>... So you can have an efficient, exception
>mechanism in a language without exceptions. BTW, the Metrowerks Modula-2
>compiler for the Macintosh(TM) provides just such a module.

This is what I REALLY like about Modula-2; the ability to expand/change
its capabilities.  I've thought about doing this very same thing (but 
haven't had time).

One of the first things I changed about M-2 was the IO.  Not liking the
standard IO modules, I wrote my own (software tools inspired).  My Modula-2
motto is "If I don't like something; don't complain, change it!".
If only I could find time to get back to a much neglected project; a
full Virtual Operating System.

-- 
Hal Chambers
hal@newton.physics.purdue.edu
hal@physics-newton.arpa

mfranz@ethz.UUCP (Michael Franz) (04/11/90)

In the Oberon Operating System, much use is made of the controlled exit
facility of the HALT statement.  A HALT forces execution of the current
command to stop, resets the stack and returns to the Operating System
Command Loop (as well as opening a viewer containing a symbolic stack dump),
but does not affect the global state of loaded modules.  The module
containing the HALT instruction, as well as all other modules, will stay
loaded and its global variables will stay intact.  A new command may
then be executed.

Oberon abandons the notion of a PROGRAM altogether.  Any module may
export COMMANDS, parameterless procedures, which may be executed
directly from the operating system interface.  These Commands take their
parameters from global variables of the OS, which include such items as the
viewer containing the insertion point and a time-stamped list of text
selections.

Granularity of these commands is quite fine.  Typical commands display
the directory of a storage device, increase the font size of the text
last selected or compile the contents of the active window.  A user may
execute commands in any sequence, and may thus be working on completely
different problems in different windows at the same time (One-process
Multitasking).  No difference is made between Commands offered by the OS
and User Commands, which are thought of as extending the basic system. 

In this environment, the safe exit via HALT is of course ideal.  A HALT
will just terminate the current command; after taking some actions,
the user may try to execute the command again.  A typical application
might be a floppy disk driver - if no disk is inserted, it is quite
cumbersome passing up this information to the module originally instructed
to display a disk directory.  In Oberon, the disk driver module would
output an error message and execute a controlled halt.  The user may
then insert a floppy disk into the drive and retry the command.

-- Michael

Michael Franz   Computersysteme   ETH Zurich   Switzerland   franz@inf.ethz.ch