comp.lang.ada
 help / color / mirror / Atom feed
* Improving Ada Exceptions
@ 1997-10-26  0:00 Ray Blaak
  1997-10-27  0:00 ` James S. Rogers
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Ray Blaak @ 1997-10-26  0:00 UTC (permalink / raw)



Hello all. I am an Ada fanatic who has just started his first C++ project.
Being thoroughly ingrained against the evils of C++ I was quite surprised to
find it not as bad as I expected. There are many horrible aspects about it, to
be sure, but one thing I find very cool is C++'s exception mechanism.

It is a very powerful thing to be able to throw and catch arbitrary objects,
since one can cleanly place whatever appropriate information is relevant to the
error. By catching objects of a base class, one can handle whole classes of
errors at once.

The Ada 83 exception method is clean and simple but suffers from the inability
to pass data with the exception. Ada 95 adds the ability to pass strings with
the exception, but in an inelegant way, in my opinion. One now has the
Ada.Exceptions library package, exception ids, exception occurrences, and
mutiple ways to raise on exception (i.e. the raise keyword and
Ada.Exceptions.Raise_Exception). Part of the complexity comes from the fact
that Ada exceptions are just names, not data objects, but the result seems a
kind of hack. Surely there can be a conceptually simpler way.

So how About extending the semantics of raise to simply allow arbitrary objects
to be raised, as in C++? To handle an arbitrary thrown object, the "when"
branches of an exception handle could look like a good-old-fashioned variable
declaration (there is already a precedent syntactically with "when e : others
=>""). Consider this simple example:

type Out_Of_Range is record
  Hi : Integer;
  Low : Integer;
  Value : Integer;
end record;
...
if (...Some Failure...)
  raise Out_Of_Range'(Hi => 0, Low => 99, Value => Input_Value);
end if;
...
exception
  when Error : Out_Of_Range =>
    Text_Io.Put_Line ("out of range. " & Integer'Image(Error.Value) &
                      " not in" & Integer'Image(Error.Low) & " .." &
                      Integer'Image(Error.Hi));
end;

Consider a heirarchy of exception types:

package Math_Exception is
  type Math_Error is tagged record with private;
  function Message_Of (Error : in Math_Error) return String;

  type Integer_Divide_By_Zero_Error is new Math_Error with private;
  -- Message_Of is inherited.
  function Bad_Denominator_Of (Error : in Integer_Divide_By_Zero_Error)
    return Integer;

  -- other error types...
private
  -- whatever...
end Math_Exception;

Now fielding a heirarchy of errors:

begin
  -- some bogus calculation    
exception
  when Error : Math_Exception.Integer_Divide_By_Zero_Error =>
    Text_Io.Put_Line 
      ("divide by zero with " 
       & Integer'Image(Math_Exception.Bad_Denominator_Of(Error)));
  when Error : Math_Exception.Math_Exception'Class =>
    -- handle any other math errors
    Text_Io.Put_Line (Math_Exception.Message_Of(Error));
end;

It seems to me that this proposal fits fairly cleanly and orthogonally with the
existing language design. Of course, I could be missing something fundamental.
I would like to see a discussion on the merits and disadvantages of this
approach. Some things I am interested in:

01. Implementation complexity: Is this hard to do? Given that this is already
    implemented in C++, and GNAT especially can take advantage of gcc's
    implementation, is there something specific to Ada that would make it more
    difficult? What about throwing controlled types?
02. Safety issues: Will this violate anything? Throwing objects containing
    pointers to static objects comes to mind. 
03. Conceptual coolness: I think that this approach makes use of existing
    syntax pretty simply and cleanly. It also, I think, does not preturb the
    existing exception mechanism. What are some problems? One might be that
    "raise" is typeless. One either has to raise a variable, or a type
    qualified literal or aggregate.
04. Anything else?

--  
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
blaak@infomatch.com                            The Rhythm has my soul.





^ permalink raw reply	[flat|nested] 13+ messages in thread
* Re: Improving Ada Exceptions
@ 1997-11-03  0:00 Marc Wachowitz
  1997-11-08  0:00 ` Wayne Magor
  0 siblings, 1 reply; 13+ messages in thread
From: Marc Wachowitz @ 1997-11-03  0:00 UTC (permalink / raw)



ok@goanna.cs.rmit.edu.au (Richard A. O'Keefe) wrote:
> throwing an exception object out of the scope of its class would be a
> possibility that would have to be blocked some way.

One way which would catch this problem in an (IMO) acceptable way,
concerning both performace and language complexity, would be to require
that the types of (potential) exception objects be subtypes of some
particular type (say, Ada.Exceptions.Dynamic_Object), and then enclose a
nested scope declaring such subtypes within an implicit handler for
all such types declared immediately at its level, which then raises a
particular exception (say, Ada.Exceptions.Out_Of_Scope) with appropriate
information to find out the full name of the type of the original
exception (this information would be intended for logging/debugging,
similar to what you can get now). Any overhead for the implicit handler
would only appear if a nested potential exception type is declared and
the compiler cannot figure out that no such exception would otherwise
escape its proper scope. (Note that in most environments, it's even
possible to implement exceptions with zero time overhead as long as they
are not raised, and the additional overhead for these implicit handlers
if an innocent exception is raised would hardly be worth worrying about.)

A somewhat different problem (which doesn't arise with CLOS, Java or C++)
is that exception categories via subtyping tend to make most sense if you
can put exceptions into several independent categories (i.e. multiple
supertyping). While multiple views can be implemented reasonably well in
Ada (and I even tend to prefer its tool-box approach to usual multiple
inheritance in most situations), this particular problem seems to demand
a more dynamic selection based on all available views, rather than only
access through some known view. I'm not sure how this would best fit into
the subtyping model of Ada-95 as we know it, and I'd fear that a naive
attempt to use a single-inheritance hierarchy as exception categorization
would easily lead to long-term trouble.

Of course, if all you need is to get some more information about the
exception through to the handler (e.g. which i/o-error happend with
which file, what was the error code from the system call), it would be
sufficient to associate an arbitrary object (with the above safety net)
with an exception, but still select exception handlers only based on an
explicitly named exception - similar to the way Modula-3 does it (which
does have garbage collection, and doesn't need such a safety net for
data, though it's still limited for nested procedures, which cannot be
assigned to any variable at all, but only passed as procedure argument).

-- Marc Wachowitz <mw@ipx2.rz.uni-mannheim.de>




^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~1997-11-10  0:00 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-10-26  0:00 Improving Ada Exceptions Ray Blaak
1997-10-27  0:00 ` James S. Rogers
1997-10-27  0:00 ` Chris Morgan
1997-10-27  0:00   ` Tucker Taft
1997-10-27  0:00   ` Larry Kilgallen
1997-10-27  0:00   ` Alan E & Carmel J Brain
1997-10-27  0:00 ` Stephen Leake
1997-10-27  0:00   ` Tom Moran
1997-10-30  0:00 ` Balmacara9
1997-11-03  0:00 ` Richard A. O'Keefe
  -- strict thread matches above, loose matches on Subject: below --
1997-11-03  0:00 Marc Wachowitz
1997-11-08  0:00 ` Wayne Magor
1997-11-10  0:00   ` Samuel T. Harris

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox