!section 04.05.05 (12) J-M Chebat 90-09-10 83-01394
!version 1983
!topic Re: AI-00159/04
It seems to me that there is no reason to allow an array declaration as
type A is array(SHORT_INTEGER range 0..SHORT_INTEGER'LAST) of boolean;
to raise an exception.
The trouble is that we cannot describe exactly when an implementation is
allowed to raise an exception in the context of such a declaration. There are
too many implicit objects that an implementation computes and that the
standard, fortunately, ignores.
Let consider the example of an array declaration. It is sensible to compute
the number of values of the index for each dimension, but it is also sensible
to compute the size of the array, adn the multipliers M1, M2, and M3, such
that M1*I + M2*J + M3*K is the offset of the component A(I,J,K), and so on...
In many architectures, the compiler writer has only one gold rule "do not
raise CONSTRAINT_ERROR if the elaboration of the array is not going to raise
STORAGE_ERROR".
I think that all we can do here is to say that an implementer should be able
to justify in terms of AI-325 the fact that its implementation raises
CONSTRAINT_ERROR computing an implicit value. In the case of type A, it will
be certainly impossible for the implementer, provided that INTEGER is larger
than SHORT_INTEGER...
Perhaps we can also allow an implementation to raise CONSTRAINT_ERROR on a
constrained array type declaration if an object of this type is greater than,
say, SYSTEM.MEMORY_SIZE (but I am not sure that SYSTEM.MEMORY_SIZE is a very
well defined value...)
*****************************************************************************
!section 04.05.05 (12) B Wichmann 90-08-15 83-01395
!version 83
!topic Meaning of INTEGER'FIRST rem (-1)
The referenced paragraph defines a relationship between INTEGER
division and remainder. However, in the case of a 2's complement
machine, INTEGER'FIRST/(-1) overflows. It is therefore not clear
if:
a) INTEGER'FIRST rem (-1) should raise CONSTRAINT_ERROR (AI-00387),
given that there is no appeal to 11.6
b) The result 0 should be produced.
Paragraph 4.5.5(14) states that:
INTEGER'FIRST rem (-1) = INTEGER'FIRST rem 1, which is clearly 0;
and also:
INTEGER'FIRST rem (-1) = -((-INTEGER'FIRST) rem (-1)), which
clearly overflows.
Paragraph 4.5.5(12) does not help since it clearly does not give all
the cases in which NUMERIC_ERROR (CONSTRAINT_ERROR, AI-00387), can
arise, since INTEGER'FIRST / (-1) will raise an exception on a
2's complement machine (ignoring 11.6).
The Language Compatible Arithmetic Standard defines the result to be
zero. (This is because the rounding function rndI gives a result in
Z, not in the integer type.) Note that this problem did not arise in
the NPL report DITC 167/90, since 'rem' is not defined in Pascal and
the coding produced to implement this (function remI, page 23), made
a special case of this.
*****************************************************************************
!section 06.02 (13) Antoine Bertier/Henry Dancy 90-10-10 83-01396
!version 1983
!topic Comment on AI-00135
The note 6.02(13) is perfectly clear and correct in that it perfectly reflects
the intent of the language, the problem being that 6.02 does not make this
intent clear enough.
6.02 (13) states in particular:
If, however, there are multiple access paths to such a parameter (for
example, if a global variable, or another formal parameter, refers to
the same actual parameter), then the value of the formal is undefined
after updating the actual other than by updating the formal. A program
using such an undefined value is erroneous.
Obviously undefined means undefined as far as the language is concerned
and the fact that the value exists is not relevant. The important point
is that this is a crucial rule on which all optimizations on parameters
are based.
Let's take some examples. Since most of those already given did refer
to global variables, let's look at some that don't.
procedure THIS_IS_ERRONEOUS is
S : STRING(1..12) := "tar sauce ";
procedure COPY(A : in STRING; B : out STRING) is
B := A;
end COPY;
begin
COPY(S(1..8), S(5..12)); -- erroneous call: overlapping slices
end THIS_IS_ERRONEOUS;
The above example is erroneous per 6.02 (13) since the part of the two formals
refer to the same part of the actual, this part is updated, and the resulting
value used.
Now this :
procedure THIS_IS_ERRONEOUS_TOO
type VECTOR is array (1..5) of FLOAT;
type MATRIX is array (1..5) of VECTOR;
A_VECTOR : VECTOR := (0.35, 0.67, 1.8, 2.0, 7.7);
A_MATRIX : MATRIX := (others => A_VECTOR);
procedure ADD (V : in VECTOR; W in out VECTOR) is
begin
for I in VECTOR'RANGE loop
W(I) := V(I) + W(I);
end loop;
end ADD;
procedure MUL (A : in MATRIX; B in out MATRIX) is
begin
for I in B'RANGE loop
for J in B(I)'RANGE loop
B(I)(J) := A(1)(J) * B(I)(1) +
A(2)(J) * B(I)(2) +
A(3)(J) * B(I)(3) +
A(4)(J) * B(I)(4) +
A(5)(J) * B(I)(5);
end loop;
end loop;
end MUL;
begin
ADD(A_VECTOR, A_VECTOR); -- erroneous call
MUL(A_MATRIX, A_MATRIX); -- erroneous call
end THIS_IS_ERRONEOUS_TOO;
As Mats Weber pointed out, 6.02(13) could be found very restrictive to
consider the call ADD(A_VECTOR, A_VECTOR) to be erroneous since, after
all, the elements of A_VECTOR are each updated once and never reused after
being updated. However, it is clear that the call to MUL(A_MATRIX, A_MATRIX)
should be considered erroneous since each element of A_MATRIX is updated
once and reused several times after being updated.
At least the note in 6.02(13) gives a simple rule and it is better to
keep it simple rather than to try to single out cases such as the ADD
in the above example. (Also note that we can avoid all these problems
just by using functions...).
*****************************************************************************
!section 13.02 (06) J-M Chebat 90-09-07 83-01393
!version 83
!topic This AI is too restrictive
!reference AI-00301/05
It seems to me that, concerning components of scalar types, this AI is more
restrictive than the LRM is.
Consider the following example,
subtype NS_NS is INTEGER range INTEGER(0) .. 255;
-- NS_NS is a nonstatic subtype and has nonstatic constraints
subtype NS_S is NS_NS range 0 .. 3;
-- NS_S is a nonstatic subtype since its type mark isn't static, but has
-- static constraints according to LRM 4.9 (11)
--
-- "A static range is a range whose bounds are static expressions. A
-- static range constraint is a range constraint whose range is
-- static"
type R is
record
C : NS_S;
end record;
for R use
record
C at 0 range 0..1; -- Legal (LAR: Yes / AI: No)
LRM 13.4(7) says,
"A component clause is only allowed for a component if any constraint on
this component and any of its subcomponents is static"
then the component clause seems to be legal.
Where the LRM speaks about static constraints, the AI is speaking of
nonstatic subtypes,
"if a record component has a nonstatic scalar subtype, no component
clause can be given for the component"
then according to the AI the constraint is illegal.
It has been argued that the current rule is more drastic than necessary. I
think it is not worth to relax. Nevertheless, it would be an error to make it
more drastic again.
An advantage of the wording of the reference manual is that it unifies the case
of composite and scalar type and also that it treats the case of private
types in the same way: two years ago Alsys argued that in an ACVC dispute that
a component clause was not allowed for a private type but the AVO rejected the
dispute on the basis that, anyway, the component had static constraints...
*****************************************************************************