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