[comp.lang.ada] Implicit Conversion

steve@dim.sm.unisys.com (Steven Holtsberg) (03/10/89)

Let me restate the problem I mentioned earlier.

Take the following program:

          with SYSTEM; use SYSTEM;

          procedure example is
            x: TINY_INTEGER;
          begin
            x:= MAX_INT - MAX_INT;
          end example;

This program compiles and runs correctly, although I expected a
run-time error (specifically NUMERIC_ERROR) when the implicit
conversion the type of MAX_INT to TINY_INTEGER was attempted.

Note that the rule for assignment states that the expression on
the right side of the := must have the same type as the variable
on the left.  The type of X is definitely TINY_INTEGER.  Thus,
the type of MAX_INT - MAX_INT has to be TINY_INTEGER.

Now, an imlpicit conversion *cannot* be performed on the universal_integer
expression "MAX_INT - MAX_INT", since this expression is not "convertible",
as defined in section 4.6 of the standard ("An implicit conversion...can only
be applied if the operand is either a numeric literal, a named number,
or an attribute; such an operand is called a convertible universal operand...").
So, I thought, each MAX_INT had to be converted to TINY_INTEGER, which I
assumed should result in the exception NUMERIC_ERROR, because MAX_INT is
larger than the largest TINY_INTEGER (127).

After reading chapter 11 (section 11.6, Exceptions and Optimization),
I see that it is OK for this program not to result in an exception.
The rule is as follows:
"...additional freedom is left to an implementation for the evaluation
of numeric simple expressions.  For the evaluation of a predefined operation,
an implementation is allowed to use the operation of a type that has a range
wider than that of the base type of the operands, provived that this delivers
the exact result .... even if some intermediate results lie outside the range
Of the base type.  The exception NUMERIC_ERROR need not be raised in such
a case."

So, here's what happens.

1.  x is of type TINY_INTEGER.
2.  Therefore, MAX_INT - MAX_INT must be of type TINY_INTEGER,
    by the definition of the assigment statement.
3.  Therefore, the "-" is a minus on TINY_INTEGER. (def. of "-", section 4.5.3).
4.  Since MAX_INT is not of type TINY_INTEGER, and can't be implicitly
    converted, the implementation is allowed to use the "-" of a
    type that has a range wider than the "base type of the operands", which
    I take to mean the operand types of "-", not the actual operands,
    MAX_INT, and MAX_INT, whose base type is universal_integer.
    So, the "-" on universal integer is used for the evaluation of
    the TINY_INTEGER "-", and this is OK, because the result is 0,
    which lies inside the range of TINY_INTEGER.

In article <030889.085958.ncohen@ibm.com> NCOHEN@IBM.COM (Norman Cohen) writes:
>
>Steven Holtsberg may have read too much into the rule (from RM 4.6(15)),
>"An implicit conversion of a convertible universal operand is applied
>if and only if the innermost complete context (see 8.7) determines
>a unique (numeric) target type for the implicit conversion...."  This
>determination can be indirect:  The innermost complete context determines
>that the righthand side of the assignment must be of type Tiny_Integer;
>since the only visible "-" operator with a result of type Tiny_Integer is
>the "-" with operands of that type, the two operands must each be of type
>Tiny_Integer; thus the conversion takes place.  In contrast, the complete
>context
>
>          Integer_Is_Symmetric: Boolean := Min_Int = -Max_Int;
>
>does not determine a unique target type for a conversion.  Furthermore,
>there is a "legal interpretation of this context without ... conversion"
>(RM 4.6(15) again), so no conversion takes place.  The unary "-" with
>an operand and result of type universal_integer is applied to Max_Int,
>and the "=" operator with operands of type universal_integer and a
>result of type Boolean is then applied to Min_Int and the result of the
>negation.
>
>Norman Cohen

What Norman Cohen says about MIN_INT - MIN_INT is true:
no conversion takes place, and a "-" on universal_integer
is used in his example.
But this does not address the problem I stated.

Also, I disagree that "..thus the conversion takes place" (see quoted
article, just before "In contrast...")
MAX_INT can't be converted to TINY_INTEGER without raising NUMERIC_ERROR,
so I believe this conversion does not take place (as I described above).

Steven Holtsberg