[comp.lang.ada] "silly"

mfeldman@seas.gwu.edu (Michael Feldman) (06/03/90)

A recent posting suggested trying the following program on my compiler:

    procedure MAIN is
        A: array(1..2, 1..3) of INTEGER;
    begin
        A := ((2,2),(3,3,3), (4,4,4,4));
    end MAIN;

Well, here are the results, in the order Irvine (HP835), Meridian (Sun-3),
Verdix (Sun-3), TeleSoft (Sun-3). In all 4 cases, the compilers flagged the
offending initialization of the array with warnings indicating that
constraint_error would be raised at execution time. What is the point
about the "silly" semantics: that the compiler should treat it as fatal?
Well, OK, maybe it should. As a teacher of compiler construction, I know
well that the question of what to treat as a fatal error is really a
matter of taste. Let's not turn this into a religious thing, OK?

   ---------- cut here ------------

    1 | procedure MAIN is
    2 |         A: array(1..2, 1..3) of INTEGER;
    3 |     begin
    4 |         A := ((2,2),(3,3,3), (4,4,4,4));
***** > "silly.ada", line 4: Exception Warning: LRM4.3.2.11 Subaggregate array bounds not the same.
***** > "silly.ada", line 4: Exception Warning: LRM4.3.2.11 Subaggregate array bounds not the same.
***** > "silly.ada", line 4: Warning: Incompatible array bounds (1..4 not compatible with 1..3).
    5 |     end MAIN;
***** > "silly.ada", line 2: Advisory Warning: Variable A never read.

5 lines compiled.
No errors detected.
4 warnings issued.

  ----------- cut here ----------

    Meridian AdaVantage v4.0  Source file: silly.ada  Page 1
    Sat Jun  2 1990 16:47:46 EDT


        1  procedure MAIN is
        2          A: array(1..2, 1..3) of INTEGER;
        3      begin
        4          A := ((2,2),(3,3,3), (4,4,4,4));
        +
    +++++W subtype check will raise constraint_error [LRM 10.6/3]
        +
        +
    +++++W value out of range will raise constraint_error [LRM 10.6/3]
        +
        +
    +++++W subtype check will raise constraint_error [LRM 10.6/3]
        +
        +
    +++++W value out of range will raise constraint_error [LRM 10.6/3]
        +
        +
    +++++W value out of range will raise constraint_error [LRM 10.6/3]
        +
        5      end MAIN;
  
  ----------- cut here ----------


Verdix Ada Compiler, Copyright 1984, 1985, 1986, 1987, 1988, 1989
Version 5.7 - Sun UNIX
Fri Apr 21 08:49:57 PDT 1989 (d)

File: /usr.MC68020/sparko/1/faculty/mfeldman/verdix/silly.ada
	compiled Sat Jun  2 16:51:16 1990
	by user mfeldman

	floating point processor MC68881

unit:	subprogram body main
	NO Ada ERRORS		UNIT ENTERED

3 statements	5 lines

*********************************  silly.ada  *********************************

   1:procedure MAIN is
   2:        A: array(1..2, 1..3) of INTEGER;
   3:    begin
   4:        A := ((2,2),(3,3,3), (4,4,4,4));
A -------------^
B ----------------^
C -----------------^
D --------------------------------^
A:warning: RM 5.2.1(2): arrays have different sizes: will raise CONSTRAINT_ERROR
B:warning: RM 3.6.1(16) and 5.2.1(2): wrong number of elements
B:warning: bounds check will raise CONSTRAINT_ERROR at runtime
B:warning: bounds check will raise CONSTRAINT_ERROR at runtime
B:warning: RM 3.6.1: bounds check will raise CONSTRAINT_ERROR at runtime
B:warning: RM 3.6.1: bounds check will raise CONSTRAINT_ERROR at runtime
C:warning: RM 3.6.1(16) and 5.2.1(2): wrong number of elements
D:warning: RM 3.6.1(16) and 5.2.1(2): wrong number of elements
   5:    end MAIN;

  ----------- cut here ----------

TeleGen2 (tm) Ada Compilation System -- Version 1.4
Copyright 1989 TeleSoft.  All rights reserved.

  File: /usr.MC68020/sparko/1/faculty/mfeldman/telesoft/silly.ada
  Date: 1990-Jun-02 16:54:55

    Front-End            : silly.ada

    Middle-Pass          : main (specification)
    Code-Generator       : main (specification)

    Middle-Pass          : main (body)
     4:         A := ((2,2),(3,3,3), (4,4,4,4));
         
>>> WARNING: Length Check will raise Constraint Error

     4:         A := ((2,2),(3,3,3), (4,4,4,4));
         
>>> WARNING: Length Check will raise Constraint Error

     4:         A := ((2,2),(3,3,3), (4,4,4,4));
         
>>> WARNING: High Check will raise Constraint_Error

     4:         A := ((2,2),(3,3,3), (4,4,4,4));
         
>>> WARNING: Matching Array Length Check will raise Constraint_Error

    Code-Generator       : main (body)

---------------------------------------------------------------------------
Prof. Michael Feldman
Department of Electrical Engineering and Computer Science
The George Washington University
Washington, DC 20052
+1-202-994-5253
mfeldman@seas.gwu.edu
---------------------------------------------------------------------------

ken@minster.york.ac.uk (06/05/90)

In article <1919@sparko.gwu.edu> mfeldman@seas.gwu.edu (Michael Feldman) writes:
>constraint_error would be raised at execution time. What is the point
>about the "silly" semantics: that the compiler should treat it as fatal?
>Well, OK, maybe it should. As a teacher of compiler construction, I know
>well that the question of what to treat as a fatal error is really a
>matter of taste. Let's not turn this into a religious thing, OK?

It's not a matter of taste for the _compiler vendor_. They _must_
compile it because it is legal Ada! It's not the fact that the compiler
spotted it - all Ada compilers I've seen spotted it! They all have to
generate code, which always generates a constrant error.

I thought Ada was targetted at high integrity mission critical
software? Is it a good idea to defer errors to run-time? I remember
being told by a FORTRAN diehard that the language was OK because a good
compiler spotted all the bad bits and warned the user. Great.

Ken

mfeldman@seas.gwu.edu (Michael Feldman) (06/06/90)

In article <644579683.25696@minster.york.ac.uk> ken@SoftEng.UUCP (ken) writes:
>In article <1919@sparko.gwu.edu> mfeldman@seas.gwu.edu (Michael Feldman) writes:
>>constraint_error would be raised at execution time. What is the point
>>about the "silly" semantics: that the compiler should treat it as fatal?
>>Well, OK, maybe it should. As a teacher of compiler construction, I know
>>well that the question of what to treat as a fatal error is really a
>>matter of taste. Let's not turn this into a religious thing, OK?
>
>It's not a matter of taste for the _compiler vendor_. They _must_
>compile it because it is legal Ada! It's not the fact that the compiler
>spotted it - all Ada compilers I've seen spotted it! They all have to
>generate code, which always generates a constrant error.
>
You make a very good point! I think the group would benefit from hearing from
an authoritative voice on this issue. A vendor? An ARG member? Does the
current interpretation of the LRM indeed _require_ that a compilation
be completed in case of a guaranteed exception that the compiler detects?
If so, I'm sure there must be a good motivation for it, but it escapes me.
Would some important principle be violated if the compiler were to treat
a sure-to-be-raised exception as a fatal error (at least optionally?)
---------------------------------------------------------------------------
Prof. Michael Feldman
Department of Electrical Engineering and Computer Science
The George Washington University
Washington, DC 20052
+1-202-994-5253
mfeldman@seas.gwu.edu
---------------------------------------------------------------------------

eachus@linus.mitre.org (Robert I. Eachus) (06/07/90)

In article <644579683.25696@minster.york.ac.uk> ken@minster.york.ac.uk writes:

> I thought Ada was targetted at high integrity mission critical
> software? Is it a good idea to defer errors to run-time? 

     No, but it is an even worse idea to allow SOME compilers to
reject a program because it thinks the program is silly, or because
as, "a matter of taste" some vendor thinks that a particular construct
is not a good idea.

     In this particular case, it is obvious at compile time that the
aggregate must be invalid, but in general it is not possible to decide
whether an aggregate is "legal" until run time:

     A: String(1..X) := "foo";

     Given that in many cases the decision must be deferred until
run-time, the chosen policy was that mismatch is never a compile-time
error, but a compiler is expected to flag a known mismatch.  A
similar, but less surprising case is:

   declare
     X: Integer;
   begin
     X := Integer'LAST + Integer'LAST;
   end;

     A compiler can flag this, and in fact it can replace the
assignment statement with "raise CONSTRAINT_ERROR;", but it is
required to generate code...

--

					Robert I. Eachus

with STANDARD_DISCLAIMER;
use  STANDARD_DISCLAIMER;
function MESSAGE (TEXT: in CLEVER_IDEAS) return BETTER_IDEAS is...

eachus@linus.mitre.org (Robert I. Eachus) (06/07/90)

In article <1936@sparko.gwu.edu> mfeldman@seas.gwu.edu (Michael Feldman) writes:

> You make a very good point! I think the group would benefit from hearing from
> an authoritative voice on this issue. A vendor? An ARG member? Does the
> current interpretation of the LRM indeed _require_ that a compilation
> be completed in case of a guaranteed exception that the compiler detects?
> If so, I'm sure there must be a good motivation for it, but it escapes me.
> Would some important principle be violated if the compiler were to treat
> a sure-to-be-raised exception as a fatal error (at least optionally?)

     I sort of already answered this, but I guess as an ARG member I
should take a swing at such a slow curve ball. :-)  There are many
useful programs which will always raise an exception.  Would you be
appalled if your compiler declined to compile the following procedure
because it always rasied an error?  After all the companion procedure
Recoverable_File_Error compiled without problem...

     with Text_IO;
     procedure Unrecoverable_File_Error(Error_Number: in Integer;
					File:  in Text_IO.File_Type;
					Message: in String) is
     begin
       if Text_IO.Is_Open(File)
       then 
         Put_Line("Unrecoverable Error" & Integer'IMAGE(Error_Number) &
		" in file " & Text_IO.NAME(File) & ":  " & Message);
         Text_IO.Close(File);
       else
         Put_Line("Unrecoverable Error" & 
		   Integer'IMAGE(Error_Number) & ":  " & Message);
       end if;
       raise TEXT_IO.DEVICE_ERROR;
     end Unrecoverable_File_Error;

     (I am only raising DEVICE_ERROR and putting the message on
CURRENT_OUT to simplify the example. I also left out the exception
handler around the close.)

     This is a simple example, but there are many embedded systems
where the only way to get out of the main program (or some subprogram)
is when an exceptional situation arises.  Also, a file reading
procedure which counts on END_OF_FILE to get out of the read loop is
considered in poor taste, but what about a program expecting to get
its input from a file-like device that will only signal EOF when it
fails?

     Now for those of you who live in the debugger...How loud would
you scream if the compiler told you:

     "After extensive analysis, it has been determined that this
procedure will always raise some exception.  Compilation Aborted."

     Note that the compiler is specifically allowed to check for
erroneous code and replace it with code which raises PROGRAM_ERROR
(1.6(10)).  This is allowed because it was felt that in some markets,
PROGRAM_ERROR during test was preferable to programs which produced
different results on different runs with the same data.  (But only in
cases not involving the non-determinism of tasking.)
--

					Robert I. Eachus

   Amiga 3000 - The hardware makes it great, the software makes it
                awesome, and the price will make it ubiquitous.

mfeldman@seas.gwu.edu (Michael Feldman) (06/07/90)

Thanks to Robert Eachus for giving just the authoritative and sensible
answer I was hoping for. IMHO it's important for language-bashers to
realize that the designers and proponents of the language they are bashing
are neither stupid nor juvenile. Obviously we will not all agree on the       
desirability of a certain way of doing a certain feature - computer folks
are the most disputatious group I know - but it is unfair and juvenile
not to at least give the designers and proponents credit for having
thought it through. Just when I get so discouraged by the flame wars
that I'm ready to swear off reading the news, I see something that
reconfirms the mature and helpful side of it. It's these little "hits"
of good stuff that keep my addiction going. Thanks again.

stt@inmet.inmet.com (06/08/90)

Re: compile-time detectable constraint errors

One revision being considered for Ada9X is that
a class of constraint errors which are clearly
detectable at compile time ("statically" detectable)
be identified in the Reference Manual,
and that a validated compiler be required to flag them.

It is not clear whether the compiler should produce a Required Warning,
or actually reject the compilation unit.  If the compiler can reject
the compilation unit, then we may have to account for conditional
compilation in the Reference Manual as well.
This is because a reasonable use of conditional compilation
may be selecting two distinct algorithms, one of which would
include a statically detectable constraint error but only
in the cases when it would *not* be selected by a controlling
IF statement.

As usual, these issues are more complex than they first appear, and
the original design of the language considered many of these problems
and had to make a choice based on conflicting requirements.
Hindsight may justify making a different choice, but it should
not do so without fully reconsidering the original concerns.

S. Tucker Taft
Intermetrics, Inc.
Cambridge, MA  02138