[comp.lang.ada] language problem

amiram@TAURUS.BITNET.UUCP (03/26/87)

A colleague of mine, Yossi Veler of AITECH has come up with the following
program in Ada, which seems to create a serious problem.

procedure boolsub is
   subtype bool is boolean range true..true;
   type arr is array(1..10) of bool;
   a : arr := (1..10 => true); -- this seems like the only legal value
begin
   a := not a;
-- Here a(1)=a(2)=...=a(10)= FALSE !!!! No exception occurs etc.
   a := (1..10 => false);
-- This does cause an exception
end boolsub;

The program seems legal : we inspected the LRM and also the implementers
guide, and we ran it on both the DDC and VERDIX compilers. It seems that
a combination of innocent features in Ada produces a result that seems to
contradict with the basic philosophy of the language, that is an object
posseses a value which is not in the appropriate type.

It seems that several features interact to produce this undesirable situation:
1) Boolean is an enumerated type, and one can take a subtype of it.
2) Boolean array operations, which are the only ones operating on all elements
of an array.
3) At run time, array assignements are not checked element by element ( I
believe in all but this case this check is indeed not required ).

Has anyone noticed this before? Is there a way out of it?

joe@petsd.UUCP (04/01/87)

In article <8703261730.AA28726@taurus> amiram@TAURUS.BITNET.UUCP writes:
>A colleague of mine, Yossi Veler of AITECH has come up with the following
>program in Ada, which seems to create a serious problem.
>
>procedure boolsub is
>   subtype bool is boolean range true..true;
>   type arr is array(1..10) of bool;
>   a : arr := (1..10 => true); -- this seems like the only legal value
>begin
>   a := not a;
>-- Here a(1)=a(2)=...=a(10)= FALSE !!!! No exception occurs etc.
>   a := (1..10 => false);
>-- This does cause an exception
>end boolsub;
>
>The program seems legal : we inspected the LRM and also the implementers
>guide, and we ran it on both the DDC and VERDIX compilers. It seems that
>a combination of innocent features in Ada produces a result that seems to
>contradict with the basic philosophy of the language, that is an object
>posseses a value which is not in the appropriate type.

Our compiler (C3Ada R00-01.02/Beta) correctly raises CONSTRAINT_ERROR on the
statement "a := not a;".

				regards,
				joe

--

 Full-Name:  Joseph M. Orost
 UUCP:       ihnp4!vax135!petsd!joe
 ARPA:	     vax135!petsd!joe@BERKELEY
 Phone:      (201) 758-7284
 US Mail:    MS 313; Concurrent Computer Corporation; 106 Apple St
             Tinton Falls, NJ 07724

cjh@petsd.UUCP (04/01/87)

[]
In article <997@petsd.UUCP> joe@petsd.UUCP (Joseph M. Orost) writes:
>In article <8703261730.AA28726@taurus> amiram@TAURUS.BITNET.UUCP writes:
>>A colleague of mine, Yossi Veler of AITECH has come up with the following
>>program in Ada, which seems to create a serious problem.
>>
>>procedure boolsub is
>>   subtype bool is boolean range true..true;
>>   type arr is array(1..10) of bool;
>>   a : arr := (1..10 => true); -- this seems like the only legal value
>>begin
>>   a := not a;
>>-- Here a(1)=a(2)=...=a(10)= FALSE !!!! No exception occurs etc.
>>   a := (1..10 => false);
>>-- This does cause an exception
>>end boolsub;
>>
>>The program seems legal : we inspected the LRM and also the implementers
>>guide, and we ran it on both the DDC and VERDIX compilers. It seems that
>>a combination of innocent features in Ada produces a result that seems to
>>contradict with the basic philosophy of the language, that is an object
>>posseses a value which is not in the appropriate type.
>
>Our compiler (C3Ada R00-01.02/Beta) correctly raises CONSTRAINT_ERROR on the
>statement "a := not a;".
>
Why is this statement illegal?  Well... what is the type of the
expression "not a" ?  It can't be "arr" because its components do not
satisfy the subrange constraint.  And there isn't any available type
with boolean components.  The type "arr" may look like a subtype of
"ARRAY(1..10) of boolean", but it isn't.  On arrays, subtype
constraints affect the bounds of indexes, not the values of
components.

Regards,
Chris

--
Full-Name:  Christopher J. Henrich
UUCP:       ...!hjuxa!petsd!cjh
US Mail:    MS 313; Concurrent Computer Corporation;
            106 Apple St; Tinton Falls, NJ 07724
Phone:      (201) 758-7288
Concurrent Computer Corporation is a Perkin-Elmer company.

ms8k#@andrew.cmu.edu.UUCP (04/02/87)

In article <8703261730.AA28726@taurus> amiram@TAURUS.BITNET.UUCP writes:
>A colleague of mine, Yossi Veler of AITECH has come up with the following
>program in Ada, which seems to create a serious problem.
>
>procedure boolsub is
>   subtype bool is boolean range true..true;
>   type arr is array(1..10) of bool;
>   a : arr := (1..10 => true); -- this seems like the only legal value
>begin
>   a := not a;
>-- Here a(1)=a(2)=...=a(10)= FALSE !!!! No exception occurs etc.
>   a := (1..10 => false);
>-- This does cause an exception
>end boolsub;
>
>The program seems legal : we inspected the LRM and also the implementers
>guide, and we ran it on both the DDC and VERDIX compilers. It seems that
>a combination of innocent features in Ada produces a result that seems to
>contradict with the basic philosophy of the language, that is an object
>posseses a value which is not in the appropriate type.

Verdix Ada v1.5 is completely bogus. Don't be amazed by problems like this.
Another example is

    type BYTE is range 0 .. 255;
    for BYTE'SIZE use 8;

Verdix compiler says that the size is too small.

    type BYTE is new POSITIVE range 0 .. 255;
    for BYTE'SIZE use 8;

same thing! 0 as a POSITIVE does not disturb it. The bit sign is still there.

    type BYTE is range -128 .. 127
    for BYTE'SIZE use 8;

is ok (at last), but is not really what was wanted. Another solution may be
an enumaration of 256 items, a little painful. 

____________________________________________________________
Marc A. Scheurer

Arpanet, Bitnet: ms8k@andrew.cmu.edu
UUCP           : seismo!andrew.cmu.edu!ms8k
____________________________________________________________



 

ROSENBLUM@SIERRA.STANFORD.EDU.UUCP (04/02/87)

I think that the LRM is pretty clear on this point.

4.5.6 (2) says that the "not" operator takes a value of
any array of boolean components, and returns a value of
the same array type.  The important words here are SAME TYPE.
3.6 (5) says that an array type is characterized by
a set of index types and a component subtype.  Thus,
in the example the value of "not A" must be a value of
the type of A, which is ARR.  Since the resulting component
values do not satisfy the component subtype constraint,
the result is NOT a value of type ARR.  Ergo, CONSTRAINT_ERROR
must be raised by the evaluation of "not A".  Note that
the fact that the expression appears in an array assignment
is not germane; the evaluation of such a "not A" in any context
should raise CONSTRAINT_ERROR.

-- David.
-------

deller@vrdxhq.UUCP (04/03/87)

In article <MS.V3.18.ms8k.80021103.harrisburg.ibm032.535.0@andrew.cmu.edu>, ms8k#@andrew.cmu.edu (Marc Scheurer) writes:
>
> Verdix Ada v1.5 is completely bogus. Don't be amazed by problems like this.
> Another example is
   ... (and other comments about Verdix Ada 1.5 [sic])

The full original posting follows below in case there is any doubt about the 
context of this reply, and is followed by code and compilation/execution 
outputs that illustrate correct handling of bit and size representations by 
VADS 5.41.  I apologize for this lengthy reply; accuracy demands it.

Verdix has never had a v1.5 compiler.  I presume Marc is referring to VADS 
5.1a, which states explicitely in its documentation that bit representations 
and size representations are NOT supported with that version.  The fatal 
diagnostics that say "type is too small" occurred naturally because of that 
lack of support.  We were adding support with the next version, so we did not 
feel the need to add a special diagnostic to say "not supported yet".

VADS 5.41 has full support for the features Marc complains about, except on 
two of the machines in our product line (CCI and Sequent).  The documentation 
clearly states whether a release supports those features or not.  Sequent (and 
other 32032 products) will have bit rep support with the next VADS release.  

VADS 5.1a, used by Marc, was last shipped around April 1986.  VADS 5.41 began 
shipping in January 1987, in stages across all products: Sun, VAX/VMS, 
VAX/UNIX-ULTRIX, Sequent, Apollo, Masscomp, CCI, 68K crosses, 1750a crosses, 
and others.  5.41 sources with bit and size representation support have been 
shipped to all of our source customers (well over 20 computers).  

As for the original problem mentioned of a constraint error being missed in 
an array operation, the Verdix 5.41 compiler does indeed fail to raise a 
constraint error as required by the RM (the code produces the correct 
"enumerical" :-) result, and only fails to raise the constraint error).

Note that raising a constraint error is not a sufficient test of correct 
execution of the statements presented.  Robert Dewar has given an excellent 
presentation at a SIGAda conference illustrating the problems with this 
apparently simple construct.  If I remember correctly (any errors are mine, 
not his) the primary problem with the assignment is that it must be atomic, 
either performed for EVERY array element, or not performed for ANY array 
element.  The code generated must ensure, at the point it detects any result 
with a constraint error, that all elements are either assigned to by the 
assignment, or that the elements assigned to so far are "backed out".  
Efficiency concerns preclude the easy out of using an intermediate temporary 
array and copying it to the result array if there are no constraint errors.

I believe that this code generation complication is part of the reason for the 
VADS compiler missed the constraint error.  The example is clearly a 
pathological test.  A type derived from a boolean but constrained to a single 
value, yet not a constant, does not appear to be very useful.  VADS is built 
to operate efficiently on types normally encountered in practice, and works 
well in those cases.  Clearly, however, there is an error in VADS 5.41 for 
this case, which requires a "more proper" solution within the compiler to 
provide both the efficiency desired and the correctness required by the RM.

As a test of the boundary conditions for our code generation with array
operations, the original code serves very well.  We would like to thank Amiram
for providing this test.  This error will be fixed in the next release of VADS.

As for VADS being "bogus", Marc is mistaken.  He is apparently operating with 
a very old VADS version that explicitly did not support the implementation 
dependent features he is interested in.  That compiler was validated, with the
noted limitations in implementation dependent features.  VADS 5.41 is validated
under the latest validation suite available at this time.

Our best identification of his site is a site that chose not to pay for 
maintenance for the system and product he is using.  Sites that have paid 
maintenance fees (including many sites within his apparent organization) are 
now receiving VADS 5.41 shipments with full support for bit and size 
representations specifications.  

Why a site might choose not to purchase maintenance is their business, but 
that decision should not then be a reason to spuriously castigate Verdix in 
such a wide forum as Usenet.

The original posting and code example follow.
Feel free to hit your "n" key at this point (if you made it this far) :-).

Steven Deller
Director, Verdix Product Support

Original posting, in toto:

In article <MS.V3.18.ms8k.80021103.harrisburg.ibm032.535.0@andrew.cmu.edu>, ms8k#@andrew.cmu.edu (Marc Scheurer) writes:
> In article <8703261730.AA28726@taurus> amiram@TAURUS.BITNET.UUCP writes:
> >A colleague of mine, Yossi Veler of AITECH has come up with the following
> >program in Ada, which seems to create a serious problem.
> >
> >procedure boolsub is
> >   subtype bool is boolean range true..true;
> >   type arr is array(1..10) of bool;
> >   a : arr := (1..10 => true); -- this seems like the only legal value
> >begin
> >   a := not a;
> >-- Here a(1)=a(2)=...=a(10)= FALSE !!!! No exception occurs etc.
> >   a := (1..10 => false);
> >-- This does cause an exception
> >end boolsub;
> >
> >The program seems legal : we inspected the LRM and also the implementers
> >guide, and we ran it on both the DDC and VERDIX compilers. It seems that
> >a combination of innocent features in Ada produces a result that seems to
> >contradict with the basic philosophy of the language, that is an object
> >posseses a value which is not in the appropriate type.
> 
> Verdix Ada v1.5 is completely bogus. Don't be amazed by problems like this.
> Another example is
> 
>     type BYTE is range 0 .. 255;
>     for BYTE'SIZE use 8;
> 
> Verdix compiler says that the size is too small.
> 
>     type BYTE is new POSITIVE range 0 .. 255;
>     for BYTE'SIZE use 8;
> 
> same thing! 0 as a POSITIVE does not disturb it. The bit sign is still there.
> 
>     type BYTE is range -128 .. 127
>     for BYTE'SIZE use 8;
> 
> is ok (at last), but is not really what was wanted. Another solution may be
> an enumaration of 256 items, a little painful. 
> 
> ____________________________________________________________
> Marc A. Scheurer
> 
> Arpanet, Bitnet: ms8k@andrew.cmu.edu
> UUCP           : seismo!andrew.cmu.edu!ms8k
> ____________________________________________________________

P.P.S. (For die hard Ada code readers :-) ).
The following program and outputs (separated by lines of +++) illustrate 
correct handling of size representations by the Verdix VADS 5.41 compiler that 
is currently shipping for Sun-3 systems.  Please note the VADS diagnostic for 
PBYTE, a type originally cited as not being handled correctly by VADS -- that 
type specification is erroneous Ada as the Marc noted (POSITIVE does not 
include zero), so I have commented out the offending lines (and left the
diagnostics in).  I added NBYTE, which uses NATURAL and does include zero.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ size.a
with UNCHECKED_CONVERSION ;
with TEXT_IO ; use TEXT_IO ;
procedure size is

  type UBYTE is range 0 .. 255;
  for UBYTE'SIZE use 8;

--type PBYTE is new POSITIVE range 0 .. 255;
-------------------------------------^A                                      ###
--### A:warning: bounds check will raise CONSTRAINT_ERROR at runtime
--for PBYTE'SIZE use 8;

  type NBYTE is new NATURAL range 0 .. 255;
  for NBYTE'SIZE use 8;

  type SBYTE is range -128 .. 127;
  for SBYTE'SIZE use 8;

  package UB_IO is new INTEGER_IO( UBYTE ) ;
  package SB_IO is new INTEGER_IO( SBYTE ) ;
  function TO_UNSIGNED is new UNCHECKED_CONVERSION( SBYTE, UBYTE ) ;

  NB : NBYTE ;
  SB : SBYTE ;
  UB : UBYTE ;

begin
  NB := 255 ;
  NB :=   0 ;
  SB := 127 ;
  PUT( "Unsigned conversion of  127 = " ) ;
  UB_IO.PUT( TO_UNSIGNED(SB) ) ;
  NEW_LINE ;
  SB := -128 ;
  UB := TO_UNSIGNED(SB) ;
  PUT( "Unsigned conversion of -128 = " ) ;
  UB_IO.PUT( UB ) ;
  NEW_LINE ;
  PUT( "Unsigned conversion of   -1 = " ) ;
  UB_IO.PUT( TO_UNSIGNED(-1) ) ;
  NEW_LINE ;

  loop
    PUT( "Enter value -128..127: " ) ;
    SB_IO.GET( SB ) ;
    PUT( "which is a value of " ) ;
    UB_IO.PUT( TO_UNSIGNED(SB) ) ;
    PUT_LINE( " unsigned" ) ;
    exit when SB = 0 ;
  end loop ;
end ;
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ compile results
=========================================
Verdix Ada Compiler, Copyright 1984, 1985, 1986
Version 5.41 - Sun 3 Unix
Fri Jan 23 15:06:21 PST 1987 (p)

File: /vc/deller/x/size.a
	compiled Thu Apr  2 07:41:41 1987
	by user deller

unit:	subprogram body size
	NO Ada ERRORS		UNIT ENTERED

37 statements	51 lines

TIMES for Front End         wall 11.52   cpu 3.80
TIMES for Code Generator    wall 2.80   cpu 1.33
TIMES for TOTAL TIME        wall 15.24   cpu 5.56
=========================================

Verdix Ada Compiler, Copyright 1984, 1985, 1986
Version 5.41 - Sun 3 Unix
Fri Jan 23 15:06:21 PST 1987 (p)

TIMES for a.ld              wall 34.42   cpu 12.30
TIMES for TOTAL TIME        wall 35.14   cpu 12.58
++++++++++++++++++++++++++++++++++++++++++++++++++++++ execution results
Script started on Thu Apr  2 07:47:53 1987
... (elided "junk")
gilligan% size.out
Unsigned conversion of  127 =  127
Unsigned conversion of -128 =  128
Unsigned conversion of   -1 =  255
Enter value -128..127: -127
which is a value of  129 unsigned
Enter value -128..127: -126
which is a value of  130 unsigned
Enter value -128..127: -10
which is a value of  246 unsigned
Enter value -128..127: -5
which is a value of  251 unsigned
Enter value -128..127: -3
which is a value of  253 unsigned
Enter value -128..127: -2
which is a value of  254 unsigned
Enter value -128..127: 1
which is a value of    1 unsigned
Enter value -128..127: 2
which is a value of    2 unsigned
Enter value -128..127: 3
which is a value of    3 unsigned
Enter value -128..127: 126
which is a value of  126 unsigned
Enter value -128..127: 0
which is a value of    0 unsigned
gilligan% exit
... (elided "junk")
script done on Thu Apr  2 07:49:09 1987
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ done
-- 
<end_message> ::= <disclaimer> | <joke> | <witty_saying> | <cute_graphic>
{verdix,seismo,umcp-cs}!vrdxhq!deller

ms8k#@andrew.cmu.edu.UUCP (04/03/87)

vrdxhq!deller@seismo.css.gov  (Steven Deller) writes:

> Verdix has never had a v1.5 compiler...

Right. I was thinking of

     Verdix Ada Compiler, Copyright 1984
     Version 4.06 - ACVC 1.5

on VAX/Ultrix. 

> ... Why a site might choose not to purchase maintenance is their business,
but 
> that decision should not then be a reason to spuriously castigate Verdix in

> such a wide forum as Usenet.

Right again. I apologize for the inaccuracy. 
____________________________________________________________
Marc A. Scheurer

Arpanet, Bitnet: ms8k@andrew.cmu.edu
UUCP           : seismo!andrew.cmu.edu!ms8k
____________________________________________________________



                                              

dday@mimsy.UUCP (04/03/87)

In article <12291368304.48.ROSENBLUM@Sierra.Stanford.EDU> ROSENBLUM@SIERRA.STANFORD.EDU (David S. Rosenblum) writes:
>I think that the LRM is pretty clear on this point.
>
You are right, but it must have been missed by almost everybody.
I tried the same program out on DEC Ada V1.3; the results were
the same (the operation completed successfully without raising
CONSTRAINT_ERROR).  But if it is impossible to efficiently handle
type and constraint checking for every possible pathological
boundary condition then I have to come down strongly in favor
of efficient implementation of constructs that programmers are
actually going to use.
-- 
UUCP:	seismo!mimsy!dday                        Dennis Doubleday
CSNet:	dday@mimsy				 University of Maryland
ARPA:	dday@brillig.umd.edu			 College Park, MD 20742
Fan of: Chicago Cubs, Chicago Bears, OU Sooners	 (301) 454-6154

eric@burdvax.UUCP (04/06/87)

in article <6109@mimsy.UUCP>, dday@mimsy.UUCP (Dennis Doubleday) says:
> ....  But if it is impossible to efficiently handle
> type and constraint checking for every possible pathological
> boundary condition ...

At least in this example, the compiler can determine if the situation
could occur at execution time, and take appropriate actions by
emitting code for the efficient common situation, or less efficient
code for the pathological case.

First, the only operators which can partake in this silliness
are NOT and XOR, and only if their operand(s) is a subtype of
a boolean type constrained to a single value (Yuch). If such
a type may exist at execution time, the compiler could emit an
if statement like the following.

	if funny_boolean_type'first != funny_boolean_type'last then
		emit efficient code for AND and XOR
	else
		emit funny code for AND and XOR
	end if;

The funny code for AND is easy, just raise CONSTRAINT_ERROR (what
could be more efficient than that :-). For XOR, a component by
component test needs to be performed for the detection of
CONSTRAINT_ERROR.

So it turns out, for efficiency at least, that the XOR operation
is the worst case, AND is the best case, and for the common case
(a boolean type with both values), an additional if statement
is needed. Remember, all of this is only for a boolean type which
could turn out to be constrained to only a single value.


Eric Marshall
Unisys Corporation
P.O. Box 517
Paoli, PA. 19301
(215) 648-7223

USENET: sdcrdcf!burdvax!eric
        {sjuvax,ihnp4,akgua,cadre}psuvax1!burdvax!eric
ARPANET: eric@burdvax.prc.unisys.com

drw@cullvax.UUCP (04/07/87)

Is the following program required to raise CONSTRAINT_ERROR (or whatever)?

procedure y is
  subtype x is range 0..100;
  a : x := 100;
begin
  a := a + 1;
end y;

This has a major bearing on the "boolean range true..true" program.

Dale
-- 
Dale Worley		Cullinet Software
UUCP: ...!seismo!harvard!mit-eddie!cullvax!drw
ARPA: cullvax!drw@eddie.mit.edu
Un*x (a generic name for a class of OS's) != Unix (AT&T's brand of such)

keith@telesoft.UUCP (04/08/87)

Dale Worley at Cullinet Software writes:

> Is the following program required to raise CONSTRAINT_ERROR (or whatever)?
> 
> procedure y is
>   subtype x is range 0..100;
>   a : x := 100;
> begin
>   a := a + 1;
> end y;
> 
First, our compiler points out the error:

          2:   subtype x is range 0..100;
               -------

>>>    Replaced underlined text by " type "

So, making that suggested modification results in correct compilation
with the runtime result:

>>> Unhandled exception: CONSTRAINT_ERROR  (Range Check)
    Raised in   Y.Y at line 5

So, yes, absolutely, constraint_error should be raised.  I assert that
you meant either
  type x is range 0..100;
or
  subtype x is integer range 0..100;
for the purposes of the question, the differences are immaterial.

Keith
-- 
Keith Allan Shillington  telesoft!keith@UCSD.ARPA       619/457-2700x388.ATT
My opinions are mine.    {ucbvax!sdcsvax,hp-sdd,bigbang}!telesoft!keith.UUCP

drw@cullvax.UUCP (04/08/87)

keith@telesoft.UUCP (Keith Shillington @prodigal) writes:
> Dale Worley at Cullinet Software writes:
> > Is the following program required to raise CONSTRAINT_ERROR (or whatever)?
> > 
> > procedure y is
> >   subtype x is range 0..100;
> >   a : x := 100;
> > begin
> >   a := a + 1;
> > end y;
> > 
> [keith replaces "subtype" with "type" so the code will compile.]
> 
> So, making that suggested modification results in correct compilation
> with the runtime result:
> 
> >>> Unhandled exception: CONSTRAINT_ERROR  (Range Check)
>     Raised in   Y.Y at line 5
> 
> So, yes, absolutely, constraint_error should be raised. [...]

But I am neither asking whether you thing that it should be raised,
nor whether your favorite implementation raises it, I am asking
whether the LRM *requires* that it be raised, or is an implementation
allowed to not raise it?

Sheesh!  Don't people understand what *standards* are?

Dale
-- 
Dale Worley		Cullinet Software
UUCP: ...!seismo!harvard!mit-eddie!cullvax!drw
ARPA: cullvax!drw@eddie.mit.edu
Un*x (a generic name for a class of OS's) != Unix (AT&T's brand of such)