Version 1.4 of ai05s/ai05-0297-1.txt
!standard 3.5.5(7) 12-03-27 AI05-0297-1/03
!class Amendment 12-02-26
!status Amendment 2012 12-02-26
!status ARG Approved 8-1-1 12-02-26
!status work item 12-02-26
!status received 12-02-03
!priority Low
!difficulty Easy
!subject First_Valid and Last_Valid attributes
!summary
The First_Valid attribute returns the smallest valid value of a static discrete
subtype that has at least one value; Last_Valid returns the largest valid value
if such a subtype.
!problem
Given a subtype which has a static_predicate (and therefore might have a non-contiguous set
of values), a user might want to know the bounds of smallest and largest values of the subtype.
This might be used, for example, in order to define a minimal subtype which includes all values
of the original (possibly non-contiguous) subtype and can be used as an index subtype of an
array type.
!proposal
Define two new attributes, First_Valid and Last_Valid.
The prefix of either attribute must be a static discrete subtype which has at least one value.
First_Valid returns the least value which satisfies both the range constraint and the predicate
of the subtype. Last_Valid returns the greatest such value.
These attributes always yield static values.
!wording
Add after 3.5.5(7) (i.e. at the end of the existing Static Semantics section):
For every static discrete subtype S for which there exists at least
one value belonging to S that satisfies any predicate of S, the
following attributes are defined:
S'First_Valid
S'First_Valid denotes the smallest value that belongs to S and
satisfies the predicate of S.
The value of this attribute is of the type of S.
S'Last_Valid
S'Last_Valid denotes the largest value that belongs to S and
satisfies the predicate of S.
The value of this attribute is of the type of S.
[Redundant: First_Valid and Last_Valid attribute_references are always static
expressions. Any explicit predicate of S can only have been specified by a
Static_Predicate aspect.]
AARM Reason:
We require there to be at least one value so that these are always values of
the subtype. (This sidesteps the question of what to return for a subtype
with no values.)
AARM discussion:
These attributes are intended primarily for use in the case
where the Static_Predicate aspect of S has been specified; First and Last
are equivalent if these are allowed and there is no predicate.
Add an AARM Note after 3.2.4(18/3):
This is to prevent confusion about whether the
First value is the lowest value of the subtype (which does not depend on the
predicate) or the lowest value of the subtype which meets the predicate.
(For a dynamic predicate, determining this latter value is expensive as it
would usually require a loop.) For a static subtype that has a static
predicate, the First_Valid and Last_Valid attributes (see 3.5.5) can be
used instead.
!discussion
One could imagine defining these attributes for nonstatic subtypes but we always want
S'First_Valid and S'Last_Valid to yield values that belong to S (speaking imprecisely,
we want them to yield valid values).
----
If the "at least one value" wording above seems too odd, we could express the same idea
by saying that the attribute prefix need only be a static discrete subtype and then adding
a separate legality rule that the attribute prefix must denote a subtype which has at least
one value.
----
The idea of the naming of these attributes is that they return the smallest (largest) value
for which Obj'Valid would be True (that is, the smallest (largest) valid value).
----
Note that the requirement that the prefix of these attributes be static prevents them from
ever being used on a subtype descended from a generic formal type (these are never static).
!corrigendum 3.5.5(7)
Insert after the paragraph:
This function returns a value of the type of S whose position number equals the
value of Arg. For the evaluation of a call on S'Val, if there is no value in the base
range of its type with the given position number, Constraint_Error is raised.
the new paragraphs:
For every static discrete subtype S for which there exists at least
one value belonging to S that satisfies any predicate of S, the
following attributes are defined:
- S'First_Valid
-
S'First_Valid denotes the smallest value that belongs to S and
satisfies the predicate of S. The value of this attribute is of the type of S.
- S'Last_Valid
-
S'Last_Valid denotes the largest value that belongs to S and
satisfies the predicate of S. The value of this attribute is of the type of S.
First_Valid and Last_Valid attribute_references are always static
expressions. Any explicit predicate of S can only have been specified by a
Static_Predicate aspect.
!ACATS Test
An ACATS C-Test should be created to test these attributes, especially in the Static_Predicate
case.
!ASIS
No change needed.
!appendix
From: John Barnes
Sent: Thursday, December 15, 2011 8:52 AM
I hate to bring up another irritation with subtype predicates but I am going to.
Randy has now posted the second part of the rationale (on aspects and contracts)
on the secret web site.
There is an example on page 15 about playing with a dartboard. At the bottom of
the right hand column there is a declaration
type Hit_Count is array (1 .. 60) of Integer...
Having to write the literals 1 and 60 is infuriating. They are the Min and Max
values of the subtype Score. We are not allowed to use 'First and 'Last on Score
and I think that is right because it would tempt one into using Range and that
seems inappropriate for a set with holes. But how about defining atttributes Min
and Max on such a subtype so I can write
type Hit_Count is array (Score'Min .. Score'Max) of ...
Just a thought.
Back to the Spark book ...
****************************************************************
From: Jean-Pierre Rosen
Sent: Thursday, December 15, 2011 9:19 AM
Well 'Min and 'Max exist already, so you'll have to find other names.
Hmm... 'Start and 'Stop?
****************************************************************
From: John Barnes
Sent: Thursday, December 15, 2011 9:48 AM
I thought we were good at overloading. Hmm.
****************************************************************
From: Randy Brukardt
Sent: Thursday, December 15, 2011 7:59 PM
We allow overloading functions, but First and Last are not functions, they're
values. And we don't allow overloading values or objects (remember that we don't
allow overloading constants, for instance).
Practically, attributes are implemented with special-case code for each
attribute. Overloading them would complicate the implementation quite a bit
(because there is no general case code that could be used).
Anyway, I don't buy the argument that these are somehow different from 'First
and 'Last. Why should you have to remember to use some other attribute names if
you want this information from a subtype with a static predicate compared to any
other subtype? The only reason that I can think of would be if there is some
confusion about the meaning.
(For the record, I properly defined 'First and 'Last in my old set constraint
proposal, because they are clearly needed; for some reason, that got dropped
from static predicates even though they still are clearly needed as John's
example shows. We could borrow the wording from the old set constraint proposal
if we wanted to define these -- or with some other names for that matter.)
The argument I remember for not defining them is that people think that
Score'First .. Score'Last should be the same as Score. I don't buy this
argument; the meta rule ought to be that the predicate is involved IFF the
subtype name is involved. So the predicate has an effect on the value of
Score'First, Score'Last, Score by itself, but ".." does not involve the name of
the subtype so no predicate is involved on that. In any case, I don't see that
saying Score'Min .. Score'Max (or Score'Start .. Score'Stop) changes meaning at
all, other than that we know have two very similar attributes.
Aside: while 'Last (or 'Max) is well-defined even for dynamic predicates, we
would not want to support that because it could be very expensive. Consider:
subtype Power_of_Two is Long_Long_Integer
with Dynamic_Predicate => Is_Power_of_Two (Power_of_Two);
Assume that Long_Long_Integer'Last is (2**127)-1. In that case,
Power_of_Two'Last (or Max) = 2**126. But to figure that out, you would need a
loop that goes from Long_Long_Integer'Last down until the predicate is True -
requiring 2**126-1 iterations. Yikes!
Aside 2: The only legitimate reason I can think of for keeping 'First and 'Min
separate is the definitional one: the lower bound of the subtype for the
purposes of the defining the value set is that of the constraint (ignoring the
static predicate). There might be a tiny amount of value being able to talk
about these separately. But I think it would be OK to merge the two ideas (at
least for static subtypes) so that the lower bound takes both the constraint and
predicate into account. In which case we do not need separate attributes.
In any case, I agree with John that there is a problem here. We need some way to
define arrays for subtypes with static predicates, and having to use literals or
constants seems like a step backwards. [That's especially true in John's
dartboard example, where the "obvious" upper bound (the inner bullseye) isn't
the upper bound at all (that's the triple 20).] It will feel especially strange
for experienced Ada programmers that always use the attributes in such
circumstances.
****************************************************************
From: Bob Duff
Sent: Tuesday, December 20, 2011 10:16 AM
> > > type Hit_Count is array (Score'Min .. Score'Max) of ...
Well, the rationale given in the AI still seems to apply:
Note that 'First is forbidden even in the static case. It would be
easy for the compiler to calculate 'First as the smallest value that
obeys the predicate and range constraint (taking care with null
ranges), but it would still be error prone, because code that uses
'First tends to assume a contiguous range. If we need that
functionality, we should define a new attribute to return the minimum
value -- but we don't.
'First might mean the lower bound of the range, or it might mean the lowest
number that obeys the predicate. It's not 100% clear which it SHOULD mean;
making it illegal avoids that confusion.
'Min seems like the perfect name for this new concept, but I agree with J.P. and
Randy that overloading the names would cause trouble. I've been considering
exactly that for my hobby language, by the way.
How about 'Min_Value or 'Min_Val or something?
I don't much like 'Start.
I think it would be appropriate to consider this as a possible enhancement for
Ada 2020. It seems way too late for Ada 2012, especially given that the
workaround doesn't seem so bad: Declare Score_Range as 1..Single'Last*3, and
then "Score is Score_Range with Static_Predicate => ...". Then you can use
Score_Range as the array index, and it's then crystal clear that the programmer
has to deal with the "holes" (by explicitly putting -1).
> We allow overloading functions, but First and Last are not functions,
> they're values. And we don't allow overloading values or objects
> (remember that we don't allow overloading constants, for instance).
Right.
> Anyway, I don't buy the argument that these are somehow different from
> 'First and 'Last. Why should you have to remember to use some other
> attribute names if you want this information from a subtype with a
> static predicate compared to any other subtype? The only reason that I
> can think of would be if there is some confusion about the meaning.
Well, I still think there's potential confusion. But I'm half convinced by
Randy's argument. Maybe I could be convinced to allow 'First in the static
case. But please let's wait for Ada 2020.
I hope we all agree that 'First should not be allowed in the dynamic case!
> The argument I remember for not defining them is that people think
> that Score'First .. Score'Last should be the same as Score.
Well, if you asked a typical Ada programmer if that's the case, they'd say
"yes".
>... I don't buy this
> argument; the meta rule ought to be that the predicate is involved IFF
>the subtype name is involved. So the predicate has an effect on the
>value of Score'First, Score'Last, Score by itself, but ".." does not
>involve the name of the subtype so no predicate is involved on that.
>In any case, I don't see that saying Score'Min .. Score'Max (or
>Score'Start .. Score'Stop) changes meaning at all, other than that we know
>have two very similar attributes.
I see your point. I'm half convinced, but it still seems too subtle for the
average programmer -- a potential "gotcha".
----
John, I noticed a couple of typos in that section (didn't read the entire
thing):
In the first type Score:
| 22 | 24 | 25 | 26 | 27 | 28 ! 30 | 32 | 33
| 34 | 36 | 38 | 39 | 40 | 42 ! 45 | 48 | 50
^
|
Those look like exclamation points, which are allowed, but obsolescent.
Page 16:
for K in Score loop
New_LIne; Put(Hit); Put(Hit_Count(K));
^
|
I should be lower case.
P.S. It's a nice example!
P.P.S. I would have done more singing-the-praises of the full coverage rules,
which (as you know) is one of my favorite features of Ada.
****************************************************************
From: Randy Brukardt
Sent: Tuesday, December 20, 2011 1:39 PM
...
> Well, I still think there's potential confusion. But I'm half
> convinced by Randy's argument. Maybe I could be convinced to allow
> 'First in the static case. But please let's wait for Ada 2020.
We have another ARG meeting before Ada 2012 will be put to bed, so we can
properly consider this issue if time permits. (It's surely not the most
important issue we could talk about, but I'd rather talk about it than Steve's
latest accessibility bug... ;-)
Most of the things that I tried to put off to Ada 2020 ended up getting
discussed in Denver and in many cases handled. (I realize that you were not
there, so you probably don't know how much was changed there - I'm still working
on the minutes, it is very slow going.)
...
> >... I don't buy this
> > argument; the meta rule ought to be that the predicate is involved
> >IFF the subtype name is involved. So the predicate has an effect on
> >the value of Score'First, Score'Last, Score by itself, but ".." does
> >not involve the name of the subtype so no predicate is involved on that.
> >In any case, I don't see that saying Score'Min .. Score'Max (or
> >Score'Start .. Score'Stop) changes meaning at all, other
> than that we know have two very similar attributes.
>
> I see your point. I'm half convinced, but it still seems too subtle
> for the average programmer -- a potential "gotcha".
I understand the worry, but that means that we should make no solution rather
than adding some other attribute (which helps not at all IMHO). But I think most
programmers will eventually find this to a be a missing capability: John's
example seems pretty typical to me.
>I think it would be appropriate to consider this as a possible enhancement for
>Ada 2020. It seems way too late for Ada 2012, especially given that the
>workaround doesn't seem so bad: Declare Score_Range as 1..Single'Last*3,
>and then "Score is Score_Range with Static_Predicate => ...".
> Then you can use Score_Range as the array index, and it's then crystal clear
> that the programmer has to deal with the "holes" (by explicitly putting -1).
The problem with this workaround is that "Single'Last*3" is just as magic was
saying "60". You have to figure it out separately from the predicate, and that
leaves an obvious source of errors.
For instance, in this example, it would be very easy to think that the bullseye
should be the high score. (I've always been surprised that it is not.) So if you
declared Score_Range as 1 .. Inner_Bullseye; (where Inner_Bullseye = 50) you
would have a problem. And the problem would not be detected easily: the
Static_Predicate would still be legal, it just would be missing a few values
(51, 54, 57, 60).
(BTW, that is a complication for defining 'First or 'Min_Value for a static
predicate -- the underlying subtype can be dynamic, meaning that it isn't
necessarily possible at compile-time to figure out which values are in the set.
I had solved this for the old set constraint proposal by having a constraint
check if there were any values of the given set outside of the range of the
parent subtype (just as we do when you declare an new range constraint of an
existing subtype). But we don't have this for static predicates (they're boolean
expressions, not sets). A static predicate on a dynamic subtype isn't very
useful, I wonder if we really ought to be allowing it. More food for thought...)
****************************************************************
From: Bob Duff
Sent: Tuesday, December 20, 2011 3:08 PM
>... (I realize that you were not
> there, so you probably don't know how much was changed there - I'm
>still working on the minutes, it is very slow going.)
In other words, the fact that we have a meeting doesn't make discussing new
features "free". ;-)
> The problem with this workaround is that "Single'Last*3" is just as
> magic was saying "60". You have to figure it out separately from the
> predicate, and that leaves an obvious source of errors.
>
> For instance, in this example, it would be very easy to think that the
> bullseye should be the high score. (I've always been surprised that it
> is
> not.) So if you declared Score_Range as 1 .. Inner_Bullseye; (where
> Inner_Bullseye = 50) you would have a problem. And the problem would
> not be detected easily: the Static_Predicate would still be legal, it
> just would be missing a few values (51, 54, 57, 60).
Good point. But I still don't like changing things at the last minute. Why do
we think this particular limitation of Ada is more important than any others?
> (BTW, that is a complication for defining 'First or 'Min_Value for a
> static predicate -- the underlying subtype can be dynamic, meaning
> that it isn't necessarily possible at compile-time to figure out which
> values are in the set. I had solved this for the old set constraint
> proposal by having a constraint check if there were any values of the
> given set outside of the range of the parent subtype (just as we do
> when you declare an new range constraint of an existing subtype). But
> we don't have this for static predicates (they're boolean expressions, not
> sets).
They're expressed as boolean expressions, but in the static case, they represent
a statically-known set, which can be represented as a sequence of ranges, whose
size is roughly proportional to the text of the predicates. The AI makes this
intent clear, I think.
>...A static predicate on a
> dynamic subtype isn't very useful, I wonder if we really ought to be
>allowing it. More food for thought...)
I thought we treated a subtype with dynamic bounds as fully dynamic, even if it
has a static predicate as well -- so 'First/'Min_Val should be illegal for those
(and use in case statements, etc).
****************************************************************
From: Randy Brukardt
Sent: Tuesday, December 20, 2011 3:37 PM
...
> Good point. But I still don't like changing things at the last
> minute. Why do we think this particular limitation of Ada is more
> important than any others?
It's not so much that it is more important, it's that it is part of getting a
new feature right. And we still can make changes in those new features without
worrying about compatibility issues. So anything reasonably simple that is of
interest potentially will be discussed. After all, in Denver we ended up
discussing a whole bunch of such ideas, including quite a few that I didn't even
have time to create AIs for beforehand. (Several of those got AIs written during
the meeting and approved.)
If this was related to something that has existed for a long time (say "in out"
parameters), it would be much less worth discussing. But "little" changes
related to predicates, preconditions, conditional expressions, etc. seem worth
discussing now; it's better to get it right in the first place. After all, the
whole reason that we agreed to take another round of review was to get more
examples created in order to find rough edges that we missed. That's exactly
what John did here, so we would be remiss to not take the opportunity to see if
there is an improvement that we can agree on.
...
> >...A static predicate on a
> > dynamic subtype isn't very useful, I wonder if we really ought to be
> >allowing it. More food for thought...)
>
> I thought we treated a subtype with dynamic bounds as fully dynamic,
> even if it has a static predicate as well -- so 'First/'Min_Val should
> be illegal for those (and use in case statements, etc).
Humm, such a subtype is not a static subtype, but otherwise it has a static
predicate. The idea originally suggested was to try these attributes to static
predicates only. But you are suggesting that 'First/'Min_Val only be allowed for
static subtypes with static predicates (and of course all subtypes that don't
have a predicate). That probably would work (since staticness can already affect
legality, it is likely OK to have it affect other legality).
****************************************************************
From: Bob Duff
Sent: Tuesday, December 20, 2011 4:48 PM
> It's not so much that it is more important, it's that it is part of
> getting a new feature right.
OK, but note:
- The change being discussed is upward compatible (allow 'First in more
cases, or add new attribute 'Min_Val).
- Time I spend thinking about this is time I'm not spending on reviewing
the RM.
> Humm, such a subtype is not a static subtype, but otherwise it has a
> static predicate. The idea originally suggested was to try these
> attributes to static predicates only. But you are suggesting that
> 'First/'Min_Val only be allowed for static subtypes with static
> predicates (and of course all subtypes that don't have a predicate).
Yes. I mean, the following are illegal:
subtype S is Integer range 1..Non_Static(...) with
Static_Predicate => ...;
...array(S) of ... -- Illegal!
case ... is
when S => ...; -- Illegal!
Right?
So it makes sense that S'First/S'Min_Val would be illegal, too, even if we make
it legal for static subtypes with static predicates.
****************************************************************
From: Randy Brukardt
Sent: Tuesday, December 20, 2011 5:07 PM
...
> - Time I spend thinking about this is time I'm not spending on reviewing
> the RM.
You mean you're spending time *not* thinking about Ada 2012? Shame on you!
;-)
...
> Yes. I mean, the following are illegal:
>
> subtype S is Integer range 1..Non_Static(...) with
> Static_Predicate => ...;
>
> ...array(S) of ... -- Illegal!
>
> case ... is
> when S => ...; -- Illegal!
>
> Right?
Right. The first case isn't interesting (it's illegal for any form of
predicate), but the second is more interesting (it's only allowed for static
subtypes, which necessarily have to have static predicates if they have any).
But how about:
for I in S loop -- Legal (I think).
I think this is legal with the current rules. S is allowed if it has a static
predicate, and there is no requirement that the subtype itself be static. Surely
S'First/S'Min_Value is no harder to implement than this combination of dynamic
and static constraints. So the question becomes whether we ought to use the same
rule here and for the attribute (if any).
And note that changing this (if we do) is *not* upward compatible, so we need to
at least decide this much now.
****************************************************************
From: Bob Duff
Sent: Tuesday, December 20, 2011 5:45 PM
> Right. The first case isn't interesting (it's illegal for any form of
> predicate),
Right, you can throw that red herring back into the ocean. ;-)
>... but the second is more interesting (it's only allowed for static
>subtypes, which necessarily have to have static predicates if they have
>any).
Right.
>... But how about:
>
> for I in S loop -- Legal (I think).
>
> I think this is legal with the current rules. S is allowed if it has a
> static predicate, and there is no requirement that the subtype itself
> be static.
Hmm. I thought that was illegal. But you are right -- it appears to be legal
according to the RM. The discussion in AI05-0153-3 seems to indicate that this
is a mistake (mea culpa). AI05-0262-1 is indicated on this para, but I see no
change for that AI.
>...Surely S'First/S'Min_Value is no harder to implement than this
>combination of dynamic and static constraints. So the question becomes
>whether we ought to use the same rule here and for the attribute (if any).
Yes, it would make sense to use the same rule.
> And note that changing this (if we do) is *not* upward compatible, so
> we need to at least decide this much now.
Indeed. I'm inclined to make the above 'for' loop illegal.
****************************************************************
From: Randy Brukardt
Sent: Tuesday, December 20, 2011 6:15 PM
...
> Hmm. I thought that was illegal. But you are right -- it appears to
> be legal according to the RM. The discussion in
> AI05-0153-3 seems to indicate that this is a mistake (mea culpa).
> AI05-0262-1 is indicated on this para, but I see no change for that AI.
I think the paragraph was split, and this sentence now stands alone. But it
wasn't actually changed.
> >...Surely S'First/S'Min_Value is no harder to implement than this
> >combination of dynamic and static constraints. So the question
> >becomes whether we ought to use the same rule here and for the
> >attribute (if any).
>
> Yes, it would make sense to use the same rule.
>
> > And note that changing this (if we do) is *not* upward compatible,
> > so we need to at least decide this much now.
>
> Indeed. I'm inclined to make the above 'for' loop illegal.
I can believe that was the intent.
In any case, now that we've found a bug we'll have to discuss it in February, so
we might as well discuss the attributes as well. See how that works? :-)
{Note: The bug is handled in AI05-0287-1. - Editor}
[Note that this has nothing to do with the quality of your work. As Adam has
demonstrated repeatedly, look hard enough anywhere in the RM (any version of the
RM) and you'll find a bug.]
****************************************************************
From: Bob Duff
Sent: Tuesday, December 20, 2011 6:44 PM
> In any case, now that we've found a bug we'll have to discuss it in
> February, so we might as well discuss the attributes as well. See how
> that works? :-)
Yes, I see. We find a bug, and we thereby open Pandora's Box. ;-)
****************************************************************
From: Robert Dewar
Sent: Saturday, February 25, 2012 8:21 PM
[He's commenting on version /01 of the AI - Editor.]
Just one question, if we have a subtype with a static range, and a non-static
predicate, is that now a non-static subtype? I didn't quite see from the below
description how to know that these attributes do not apply in the case where there
is a non-static predicate???
****************************************************************
From: Randy Brukardt
Sent: Saturday, February 25, 2012 10:22 PM
> Just one question, if we have a subtype with a static
> range, and a non-static predicate, is that now a non-static subtype?
No "now" about it. It's always been the case that a dynamic predicate makes a subtype
nonstatic (see 4.9(26/3)). The "bug" was that a nonstatic subtype with a static
predicate was still allowed in loops (and these future attributes).
> I didn't quite see from the below description how to
> know that these attributes do not apply in the case where
> there is a non-static predicate???
Please note that what Steve sent is an AI12, which contain corrections and extensions
to Ada *2012*. Essentially, this proposal was rejected for immaturity for Ada 2012
(to be essentially finalized tomorrow - only two AIs remain tonight), and Steve was
assigned to write up what we had considered to be reconsidered for some future version
of Ada. (Which we usually call "Ada 2020").
****************************************************************
From: Robert Dewar
Sent: Sunday, February 26, 2012 2:16 AM
...
> No "now" about it. It's always been the case that a dynamic predicate
> makes a subtype nonstatic (see 4.9(26/3)). The "bug" was that a
> nonstatic subtype with a static predicate was still allowed in loops
> (and these future attributes).
OK, thanks for the clarification, that makes sense
****************************************************************
From: Robert Dewar
Sent: Sunday, February 26, 2012 2:17 AM
...
> Please note that what Steve sent is an AI12, which contain
> corrections and extensions to Ada *2012*. Essentially, this proposal
> was rejected for immaturity for Ada 2012 (to be essentially
> finalized tomorrow - only two AIs remain tonight), and Steve was
> assigned to write up what we had considered to be reconsidered for
> some future version of Ada. (Which we usually call "Ada 2020").
OK, sounds good, new proposal sounds reasonable, and we will go ahead and implement
these attributes as impl-defined in GNAT.
****************************************************************
From: John Barnes
Sent: Sunday, February 26, 2012 8:39 AM
So I can use First_Valid and Last_Valid in my example of playing darts.
Excellent
****************************************************************
From: Bob Duff
Sent: Sunday, February 26, 2012 12:06 PM
> So I can use First_Valid and Last_Valid in my example of playing darts.
This is an Ada 2020 feature, not 2012!
****************************************************************
From: Robert Dewar
Sent: Sunday, February 26, 2012 12:12 PM
Well that's only a theoretical distinction, since in practice the only Ada 2012
compiler is GNAT for now (and who knows for how longer, probably a long time),
and GNAT will implement First_Valid and Last_Valid, the answer is yes, and in
any case, the answer is yes using the software present tense :-)
****************************************************************
From: Bob Duff
Sent: Sunday, February 26, 2012 12:24 PM
John is writing a book about Ada 2012, not about GNAT!
****************************************************************
From: Robert Dewar
Sent: Sunday, February 26, 2012 12:38 PM
Right, but there won't be much distinction between the two for most readers. As i
say, it is a pity we don't just put these attributes in Ada 2012, it serves no
purpose to leave them out, except some aesthetic concern about 100% right language
in the RM :-)
****************************************************************
From: Randy Brukardt
Sent: Sunday, February 26, 2012 12:06 PM
> So I can use First_Valid and Last_Valid in my example of playing darts.
Not yet, it won't be in Ada 2012. So the Rationale better skip it. It seems
that GNAT will support it.
****************************************************************
From: Robert Dewar
Sent: Sunday, February 26, 2012 12:13 PM
It seems a shame not to shove it into Ada 2012 when in practice all Ada 2012
compilers will support it and it seems very straightforward.
****************************************************************
From: Tucker Taft
Sent: Sunday, February 26, 2012 12:29 PM
After further discussion, we changed our collective mind, and just approved
moving the First_Valid/Last_Valid attribute into 2012 (in section 3.5.5).
[Note that these messages came in real-time during the ongoing ARG meeting
#46. The wonders of modern technology - I remember getting ARG meeting notes
on paper a month after the meeting back in the 1980s. - Editor.]
****************************************************************
From: Robert Dewar
Sent: Sunday, February 26, 2012 12:40 PM
Gosh, and I thought I would be able to implement it *before* it got into the
language :-)
BTW, it was a surprise to me that the following is illegal
> procedure ss (rmin : integer) is
> subtype r is integer range 1 .. 10;
> with Dynamic_Predicate => r >= rmin;
> rr : r;
> begin
> case rr is
> when 1 .. 10 => null;
> end case;
> end;
GNAT does not catch this case, something to fix, I wonder how many more similar
surprises there are?
****************************************************************
From: Randy Brukardt
Sent: Tuesday, March 13, 2012 7:11 PM
(Please Bob, forget the "I told you so" - Randy).
I'm afraid that we were so focused on the names of these attributes that we never
bothered to check the actual wording. (And I put it into the standard draft before
I realized that it is complete junk.)
Steve proposed:
For every static discrete subtype S for which there exists at least
one value belonging to S, the following attributes
are defined:
S'First_Valid
S'First_Valid denotes the smallest value that belongs to S.
The value of this attribute is of the type of S.
S'Last_Valid
S'Last_Valid denotes the largest value that belongs to S.
The value of this attribute is of the type of S.
The problem with this is that predicates don't modify the value set of a subtype, and they don't
have any effect on the "belongs" relationship. Just look at 4.5.2(29/3):
The membership_choice is a subtype_mark, the tested type is scalar, the value of the
simple_expression belongs to the range of the named subtype, and the predicate of the named
subtype evaluates to True.
So the problem is that both the lead-in and the definitions are completely wrong.
The problem with the lead-in is that just because there is "one value belonging to S" doesn't
mean that there are any values that satisfy the predicate (and that's the point). The problem
with the bullets is that they don't mention the predicates.
The fix is fairly easy, I think (hope?):
For every static discrete subtype S for which there exists at least
one value belonging to S {that satisfies any predicate of S}, the following attributes
are defined:
S'First_Valid
S'First_Valid denotes the smallest value that belongs to S {and
satisfies any predicate of S}. The value of this attribute is of the type of S.
S'Last_Valid
S'Last_Valid denotes the largest value that belongs to S {and
satisfies any predicate of S}. The value of this attribute is of the type of S.
****************************************************************
From: Tucker Taft
Sent: Tuesday, March 13, 2012 8:30 PM
Good catch.
I think we all just believed that "belong" took static predicates into account, but alas,
I think we argued with ourselves about that for a long time and ultimately decided it
shouldn't.
I don't remember all the reasons, but they are too late to reexamine at this point...
****************************************************************
Questions? Ask the ACAA Technical Agent