CVS difference for ai05s/ai05-0153-1.txt
--- ai05s/ai05-0153-1.txt 2012/02/04 09:07:38 1.13
+++ ai05s/ai05-0153-1.txt 2012/02/19 04:48:04 1.14
@@ -5620,3 +5620,3446 @@
****************************************************************
+From: Robert Dewar
+Date: Tuesday, September 28, 2010 11:47 AM
+
+> I *am* suggesting that the programmer should do the extra work when
+> they define a subtype with a predicate to make sure that 'First and
+> 'Last satisfy the predicate.
+
+AARGH! That's horrible
+
+That means if I have
+
+ type X is (giant list)
+
+ subtype S is X with
+ predicate => S in (J, K, L);
+
+you expect the programmer to go the trouble of writing a range after finding out
+the minimum and maximum among J, K, L, just so that 'First and 'Last sort of
+work?
+
+I find that an absurd amount of extra work, and also highly unmaintainable, this
+means that if you change the order of literals in X, you can invalidate subtype
+declarations. the whole idea of subtype declarations is to free you of such
+considerations.
+
+And what about
+
+ subtype S is Integer with
+ Predicate => Some_Very_Complex_Predicate (S);
+
+Now I am expected to run a program to find out the minimum and maximum integer
+values that satisfy this predicate (it may be out of the question to do by
+hand). And what if Some_Very_Complex_Predicate depends on the day of the month?
+Am I supposed to rewrite the program every day.
+
+I *MUST* be misunderstanding this proposal!
+
+****************************************************************
+
+From: Bob Duff
+Date: Tuesday, September 28, 2010 12:15 PM
+
+> And suppose you started with:
+>
+> subtype S1 is something range 1..100;
+> subtype S2 is S1;
+
+If somebody somewhere says "for X in S2'First .. S2'Last - 1 loop", then adding
+a predicate to S2 will introduce a bug. The more I think about it, the more I
+like Robert's idea of outlawing 'First on subtypes with predicates, so if you
+add a predicate to S2, such things will be detected at compile time.
+
+We already decided to outlaw "for X in S2 loop", if S2 has a predicate. You
+shouldn't be allowed to sneak around that rule by using attributes.
+
+****************************************************************
+
+From: Bob Duff
+Date: Tuesday, September 28, 2010 12:11 PM
+
+> AARGH! That's horrible
+>
+> That means if I have
+>
+> type X is (giant list)
+>
+> subtype S is X with
+> predicate => S in (J, K, L);
+
+Right, we need to keep in mind that (as Robert keeps saying) enumeration
+[sub]types are the main uses of predicates. And (as I keep saying), types
+related to enumeration types (e.g. a predicate on a discriminant that is of enum
+type).
+
+How about:
+
+ 1. Define staticness of predicates as Robert suggested
+ earlier.
+
+ 2. Subtype with predicate is allowed in a case 'when',
+ only if static.
+
+ 3. 'First &c not allowed (or raise exc in generic)
+ if there's a non-static predicate.
+
+ 4. If the predicate is static, 'First returns the smallest
+ value for which the predicate is True; if there is none,
+ then <something>. This can be calculated easily at
+ compile time by sorting the values.
+
+Actually, never mind (4). 'First isn't really useful when you have predicates
+-- just outlaw it. That seems simpler than Tuck's most recent proposal(s).
+
+****************************************************************
+
+From: Robert Dewar
+Date: Tuesday, September 28, 2010 12:39 PM
+
+and MUCH better, I would skip 4, not worth the effort
+
+What does &c mean, what does it include, just 'Last and 'Range?
+
+****************************************************************
+
+From: Bob Duff
+Date: Tuesday, September 28, 2010 12:55 PM
+
+Yes. I think Pred and Image and so on can be ignored with respect to predicates
+-- they are type based (possibly confusing, but we're not changing that fact).
+
+****************************************************************
+
+From: Robert Dewar
+Date: Tuesday, September 28, 2010 1:02 PM
+
+Right, I agree, I think I may output a warning!
+
+****************************************************************
+
+From: Robert Dewar
+Date: Tuesday, September 28, 2010 12:40 PM
+
+...
+> Right, we need to keep in mind that (as Robert keeps saying)
+> enumeration [sub]types are the main uses of predicates.
+
+Well if you say that too loudly, Randy will demand that we go back to the
+enumeration set constraint proposal :-)
+
+And for the record, Bob has convinced me that the more general form of
+predicates is valuable!
+
+But for sure enumeration subtypes must work, and for that we do need the notion
+of staticness. The staticness would presumably affect two things
+
+ static value in static subtype
+
+would be static
+
+and it would be allowed in a case statement
+
+****************************************************************
+
+From: Tucker Taft
+Date: Tuesday, September 28, 2010 1:30 PM
+
+I'm wondering whether we should disallow passing a scalar subtype with a
+predicate to a generic formal scalar subtype unless the formal scalar subtype is
+declared as:
+
+ type T is (<>)
+ with Predicate;
+
+or
+
+ type T is range <>
+ with Predicate;
+
+etc. Such a formal would allow a subtype with or without a predicate.
+
+This would eliminate the need to ever raise Program_Error on T'Last in the
+instance, as you would know at compile-time whether the subtype might have a
+predicate. The various Text_IO generic subpackages would presumably specify
+"with Predicate".
+
+****************************************************************
+
+From: Steve Baird
+Date: Tuesday, September 28, 2010 1:54 PM
+
+Would/should this generalize to allow specifying that a formal limited type has
+available streaming attributes?
+
+Maybe this is a just a solution in search of a problem, but it did come to mind
+when I saw your suggestion.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Tuesday, September 28, 2010 2:03 PM
+
+This seems fine to me, more implementation work, but not that significant!
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Thursday, September 30, 2010 10:45 PM
+
+...
+> But for sure enumeration subtypes must work, and for that we do need
+> the notion of staticness. The staticness would presumably affect two
+> things
+>
+> static value in static subtype
+>
+> would be static
+>
+> and it would be allowed in a case statement
+
+Despite previous statements, I don't care that much about the syntax. What I do
+care about is the effort needed to get the semantics well-defined.
+
+As I'm sure you know, there is no correlation between the effort needed to
+describe something in Standard wording, the implementation effort, and the "big
+picture" description.
+
+What you are asking for in a "static predicate" is really for the semantics of
+set constraints using the predicate syntax. This matters because a predicate
+does not change set of values that "belongs" to a subtype, while a constraint
+does change this set. Predicates are just an additional runtime check on the
+value, they don't change the value set or any other semantics.
+
+In order for the case statement to work, we need to change the set of values
+that "belongs" to a subtype, or some other change to the semantics of the
+subtype. (Given that the currrent wording in 3.8.1(9-13) includes subtypes in
+"discrete_range", the easiest fix is to change the rules for "belongs to a
+discrete_range" to take into account set values. That's what I did for the set
+constraint. But given the bizarreness of calling a static set predicate a
+"discrete_range" when 'First and 'Last aren't even being allowed to be
+referenced explicitly, maybe we need to do more major surgery).
+
+Set constraints also allow iteration (unlike non-static predicates). I think
+this is important, as it is common to use a loop to try all possible values when
+unit testing. For a predicate (not allowed to directly iterate), the intent was
+that you would write something like:
+
+ for P in S'First .. S'Last loop
+ if P in S then -- Call tested subprogram
+ -- else not in set, ignore.
+ end if;
+ end loop;
+
+However, since you don't want to allow the use of 'First and 'Last here, you'll
+have to use S'Base'First and S'Base'Last instead. (That will be a disaster if
+the base type is 64-bit integers; indeed, this is a reason that we don't allow
+iteration of subtypes with predicate as the compiler would have to generate some
+similar thing for many predicates, and that is not going to work well for 64-bit
+types.)
+
+Now, for a "static predicate", it is necessary that the compiler to be able to
+enumerate all of the members of the set (else it is impossible to check the
+coverage for case statements). So the reason to disallow iteration does not
+exist. Also note that since we're already allowing more uses for "static
+predicates" than normal "predicates", there really is no problem with allowing
+iteration as well as case statements.
+
+Also note that a "static predicate" effectively has the value of an aspect
+changing legality of a program. That is something that we've tried to avoid in
+the past (but not always). In this case, it is even worse, as the *form* of the
+expression used in the predicate is significant. As I understand it, you are
+proposing that
+ subtype S is T with predicate => S in (1 .. 3 | 8 .. 10); is a static predicate, while
+ subtype R is T with predicate => S in 1 .. 3 or S in 8 .. 10; is not. This is nasty given that the vertical bar might be read "or" in this case. (Note that we can change the rules around in various ways to eliminate cases exactly like this one, but
we'll always be able to have such cases by just making the expression more complex.) This is a (somewhat minor) maintenance hazard.
+
+With all of these factors included, I still think predicates and whatever you
+call this (static predicates; set constraints; or muggywomps ;-) are really
+different (but possibly related) features. Probably there ought to be some
+syntactic indication that you want a static predicate, such that if the
+expression doesn't have the appropriate magic form, the subtype immediately gets
+rejected rather than some use of the subtype in some other unit far away. Such
+an indication doesn't need to be as radical as the set constraint syntax
+(indeed, it doesn't make sense to do that if we are going to have predicates
+anyway).
+
+One easy option would be to have two related aspects, "predicate" and
+"static_predicate" (or, as I would prefer, "set_predicate"); with
+"set_predicate" defining a predicate *and* a bunch of additional capabilities
+(case statements and for loops), but requiring some restricted form of the
+predicate expression.
+
+One would presume to extend Tucker's "with predicate" idea for generic formals
+to handle the different kinds as well, reducing the need for Program_Error.
+
+P.S. Is anyone planning to propose an alternative AI that allows for static
+predicates? (I think we want the version that we mostly agreed upon in Valencia
+as a baseline without these bells and whistles.)
+
+****************************************************************
+
+From: Robert Dewar
+Date: Friday, October 1, 2010 7:12 AM
+
+...
+> As I'm sure you know, there is no correlation between the effort
+> needed to describe something in Standard wording, the implementation
+> effort, and the "big picture" description.
+
+*No* correlation is too strong, but often it is the case that a formal
+description can be simple, and the implementation hard, or vice versa, and
+sometimes the formal description can be hard and the informal one simple, or the
+other way round (own variables in algol-60 are a good example, the formal
+description is trivial, but the informal description and implementation are a
+mess).
+
+> In order for the case statement to work, we need to change the set of
+> values that "belongs" to a subtype, or some other change to the
+> semantics of the subtype. (Given that the currrent wording in
+> 3.8.1(9-13) includes subtypes in "discrete_range", the easiest fix is
+> to change the rules for "belongs to a discrete_range" to take into
+> account set values. That's what I did for the set constraint. But
+> given the bizarreness of calling a static set predicate a
+> "discrete_range" when 'First and 'Last aren't even being allowed to be
+> referenced explicitly, maybe we need to do more major surgery).
+
+Well remember that the fact that we don't allow explicit 'First and 'Last has
+nothing to do with the formal description, you can perfectly well maintain the
+existence of these as a formal description device.
+
+After all suppose you decide after all this discussing to allow 'First and 'Last
+after all, what's the impact on the implementation. Minimal, you make the
+message a warning message, and remove the raise of PE for generics. What's the
+impact on the user? Not much, most users pay attention to warnings much as they
+do to errors, in fact a lot of users use -gnatwe in gnat to convert all warnings
+to errors anyway.
+
+> Set constraints also allow iteration (unlike non-static predicates). I
+> think this is important, as it is common to use a loop to try all
+> possible values when unit testing. For a predicate (not allowed to
+> directly iterate), the intent was that you would write something like:
+>
+> for P in S'First .. S'Last loop
+> if P in S then -- Call tested subprogram
+> -- else not in set, ignore.
+> end if;
+> end loop;
+
+I am dubious about the value of this, I have never ever needed to iterate
+through such a beast, but I understand the point you are making about unit
+testing.
+
+> However, since you don't want to allow the use of 'First and 'Last
+> here, you'll have to use S'Base'First and S'Base'Last instead. (That
+> will be a disaster if the base type is 64-bit integers; indeed, this
+> is a reason that we don't allow iteration of subtypes with predicate
+> as the compiler would have to generate some similar thing for many
+> predicates, and that is not going to work well for 64-bit types.)
+
+There is no difficulty in using 'First and 'Last in the description of the loop.
+And given that we have an "as if" implementation rule always, the formal
+description could use 'Base'First and 'Base'Last with the understanding that an
+implementation might do things more efficiently.
+
+(there is nothing to stop implementations from using a recursive definition of
+multiplication using addition, but it's not a very good idea, but if it
+simplified the description we could describe multiplication that way, and if
+that seems far fetched, just remember that the definition of exponentiation is
+EXACTLY like that, the description uses repeated multiplication, but the
+implementation presumably and hopefully does not)
+
+Indeed I would say the better approach for implementation in the static case
+would be to build a static array of the values in the subtype, and then iterate
+through that array. This is the same "as if" result. Iterating from 'First to
+'Last can still be quite painful if you have a giant enumeration type, and a
+subtype with a couple of values at big distance from one another.
+
+> Now, for a "static predicate", it is necessary that the compiler to be
+> able to enumerate all of the members of the set (else it is impossible
+> to check the coverage for case statements). So the reason to disallow
+> iteration does not exist. Also note that since we're already allowing
+> more uses for "static predicates" than normal "predicates", there
+> really is no problem with allowing iteration as well as case statements.
+
+I tend to agree, not that hard to allow loops in this case, so why not?
+Note by the way that "enumerating all members of the set" is not something that
+is needed in the case statement, since once you have verified that a set
+predicate is static, you just plop it into the case statement, and normal
+analysis does everything else.
+
+But one minor thought, what about
+
+ type Vowel is (A, E, I, O, U);
+
+ subtype V is Vowel range I .. U with
+ V in A or U;
+
+do we want to allow that and eliminate A from the value set? I find that ugly. I
+would either say that an explicit range makes predicate non-static, or that if
+you have an explicit range it must be static and all the values in the static
+predicate have to be within that range. I would go for allowing this, but
+deciding that staticness requires no explicit range to be present. It's nonsense
+to have a range anyway when you are defining these predicates that are really
+set constraints at some informal conceptual level.
+
+> Also note that a "static predicate" effectively has the value of an
+> aspect changing legality of a program. That is something that we've
+> tried to avoid in the past (but not always).
+
+Well lots of aspects affect legality
+
+ type X is new Integer with
+ Size => 3;
+
+is illegal
+
+> In this case, it is even worse, as the *form* of the expression used
+> in the predicate is significant. As I understand it, you are proposing
+> that
+> subtype S is T with predicate => S in (1 .. 3 | 8 .. 10); is a
+> static predicate, while
+> subtype R is T with predicate => S in 1 .. 3 or S in 8 .. 10;
+> is not. This is nasty given that the vertical bar might be read "or"
+> in this case. (Note that we can change the rules around in various
+> ways to eliminate cases exactly like this one, but we'll always be
+> able to have such cases by just making the expression more complex.)
+> This is a (somewhat minor) maintenance hazard.
+
+I don't really mind allowing OR (and OR ELSE?) as well as the set notation, but
+was trying to keep things simple. The nice thing about the set notation is that
+it is exactly what you would write in the case statement.
+
+Note that it is already the case that the legality of a program depends on
+expressions being static, and the rules of whether expressions are static are
+not are as you know quite delicate!
+
+> With all of these factors included, I still think predicates and
+> whatever you call this (static predicates; set constraints; or
+> muggywomps ;-) are really different (but possibly related) features.
+> Probably there ought to be some syntactic indication that you want a
+> static predicate, such that if the expression doesn't have the
+> appropriate magic form, the subtype immediately gets rejected rather
+> than some use of the subtype in some other unit far away. Such an
+> indication doesn't need to be as radical as the set constraint syntax
+> (indeed, it doesn't make sense to do that if we are going to have predicates anyway).
+
+A concern
+
+> One easy option would be to have two related aspects, "predicate" and
+> "static_predicate" (or, as I would prefer, "set_predicate"); with
+> "set_predicate" defining a predicate *and* a bunch of additional
+> capabilities (case statements and for loops), but requiring some
+> restricted form of the predicate expression.
+
+I think I prefer to call this Set_Predicate if we go that way, because it also
+emphasizes the syntactic form. On the other hand this business of delicate rules
+on form of expressions affecting legality far away are common in the language
+now with static expressions, so what's the big deal:
+
+ type Wrapped_Integer is record
+ Int : Integer;
+ end record;
+ for Wrapped_Integer'Size
+ use Integer'Size;
+
+ B : constant Integer := ... + ref to Wrapped_Integer'Size;
+ C : constant Integer := ... + ref to Integer'Size;
+
+Now B and C have identical values and will generate identical code wherever they
+are used EXCEPT that you can't use B in a context requiring a static expression
+(like a case statement in a remote unit).
+
+The proposal to add a separate aspect Set_Predicate would be analogous to
+getting worried about this and proposing something like
+
+ C : static constant Integer := ...
+
+which is not a terrible idea at all (and we sort of have this a bit with number
+declarations), but we have lived without it for 20 years, is it really worth
+getting worried about in the relatively minor context of predicates? I think
+not.
+
+> One would presume to extend Tucker's "with predicate" idea for generic
+> formals to handle the different kinds as well, reducing the need for
+> Program_Error.
+
+Seems like an unnecessary complication to me in practice, and I think it will
+just be a nuisance. Is it really worth this nuisance just to deal with the
+marginal obscure case of using 'First and 'Last?
+
+> P.S. Is anyone planning to propose an alternative AI that allows for
+> static predicates? (I think we want the version that we mostly agreed
+> upon in Valencia as a baseline without these bells and whistles.)
+
+Bob is working actively on this (to catch up with the implementation effort :-))
+I would include the bells and whistles from the start, we really must have the
+case statements working right.
+
+By the way, I have predicates fully working except for the staticness aspect.
+For now 'Size etc are illegal (and raise PE in generics). Of course that is easy
+to change later, and better at the implementation level to go from illegal to
+legal than the other way round.
+
+****************************************************************
+
+From: Bob Duff
+Date: Friday, October 1, 2010 9:30 AM
+
+> P.S. Is anyone planning to propose an alternative AI that allows for
+> static predicates? (I think we want the version that we mostly agreed
+> upon in Valencia as a baseline without these bells and whistles.)
+
+I am planning to produce a new version of this AI as soon as possible.
+(It's turning out to be a lot harder than I thought, surprise,
+surprise.) I would prefer it to be a new version of the same AI -- we can
+always see what the old one was (that's what CVS is for).
+
+As I've said many times, for Ada 2012 (as opposed to 95 and 2005) I'm more
+concerned about implementation difficulty than wording difficulty (etc). But
+since Robert is steaming ahead with the implementation, and it's turned out
+not-so-hard, I should try to update the proposed RM wording.
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Friday, October 1, 2010 3:46 PM
+
+The whole idea of static predicates is a new one and not really related to the
+existing proposal (it's much more related to set constraints than predicates).
+The only reason we didn't approve AI05-0153-1 in Valencia was that we didn't
+agree on the wording for the new restrictions on composite predicate
+expressions. So I would prefer to have the existing AI reflect the decisions of
+that meeting exactly; and have a separate alternative with the more complex
+proposal that is now being crafted here. That way, we can see if it really is
+more complex or not.
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Friday, October 1, 2010 4:07 PM
+
+...
+> But one minor thought, what about
+>
+> type Vowel is (A, E, I, O, U);
+>
+> subtype V is Vowel range I .. U with
+> V in A or U;
+>
+> do we want to allow that and eliminate A from the value set?
+
+The set constraint proposal includes a check that each value of the set belongs
+to the range of the parent subtype. (It also doesn't syntactically allow the
+above, of course.) So the intent there is that something like this would raise
+Constraint_Error (and in this case [and most other cases], the compiler would
+issue a warning that it would always do that).
+
+That has the advantage that we don't have to worry about non-static ranges, in
+that they get checked and then can be ignored (either the subtype raises
+Constraint_Error, in which case no one can use it, or it is OK to treat it as
+static). This is similar to what happens for ranges themselves: only the "last"
+range has any semantic effect other than in the declaration of the subtype.
+
+That way, if we have:
+
+ subtype W is range Function_returning_I .. U;
+ subtype V is W with Set_Predicate => V in (A | U);
+
+V also raises Constraint_Error or works as if it is static.
+
+...
+> > Also note that a "static predicate" effectively has the value of an
+> > aspect changing legality of a program. That is something that we've
+> > tried to avoid in the past (but not always).
+>
+> Well lots of aspects affect legality
+>
+> type X is new Integer with
+> Size => 3;
+>
+> is illegal
+
+That's not what I meant; I'm talking about things other than aspects. There are
+few aspects that affect the legality of anything other than other aspects.
+
+...
+> Note that it is already the case that the legality of a program
+> depends on expressions being static, and the rules of whether
+> expressions are static are not are as you know quite delicate!
+
+This is definitely true. But just because Ada does something wrong currently
+doesn't mean we have to repeat that in new features. (For instance, we require
+matching rather than ignore the subtypes for new features in renaming.)
+
+...
+> > One easy option would be to have two related aspects, "predicate"
+> > and "static_predicate" (or, as I would prefer, "set_predicate");
+> > with "set_predicate" defining a predicate *and* a bunch of
+> > additional capabilities (case statements and for loops), but
+> > requiring some restricted form of the predicate expression.
+>
+> I think I prefer to call this Set_Predicate if we go that way, because
+> it also emphasizes the syntactic form. On the other hand this business
+> of delicate rules on form of expressions affecting legality far away
+> are common in the language now with static expressions, so what's the
+> big deal:
+>
+> type Wrapped_Integer is record
+> Int : Integer;
+> end record;
+> for Wrapped_Integer'Size
+> use Integer'Size;
+>
+> B : constant Integer := ... + ref to Wrapped_Integer'Size;
+> C : constant Integer := ... + ref to Integer'Size;
+>
+> Now B and C have identical values and will generate identical code
+> wherever they are used EXCEPT that you can't use B in a context
+> requiring a static expression (like a case statement in a remote
+> unit).
+
+Correct of course; but this particular case is a major problem (at least it has
+been in my code) because it is common to want to write a representation clause
+like R'Size use Component_1'Size + Component_2'Size, and this is illegal if
+either of the components are composite. I usually end up using the literal value
+and adding some code somewhere "if <literal> /= Component_1'Size +
+Component_2'Size then raise Program_Error; end if;". This is silly at the best.
+
+So I don't have much sympathy for using the existence of a major annoyance in
+Ada to justify introducing another similar maintenance hazard.
+
+> > One would presume to extend Tucker's "with predicate" idea for
+> > generic formals to handle the different kinds as well, reducing the
+> > need for Program_Error.
+>
+> Seems like an unnecessary complication to me in practice, and I think
+> it will just be a nuisance. Is it really worth this nuisance just to
+> deal with the marginal obscure case of using 'First and 'Last?
+
+Don't know. I've been presuming that Tucker is proposing a general feature that
+could be used on a variety of aspects. As Steve suggested, it could be used to
+require types to have available stream attributes. If that's the case, there
+isn't much additional cost to supporting one additional aspect.
+
+OTOH, if it is just a special-case gizmo, I think I'd oppose it on the grounds
+of adding more complexity to the language for little gain.
+
+But note that the major use isn't for 'First and 'Last, it is in (dis)allowing
+the use of the subtype in array indexes and slices. That's both more likely to
+happen and much more important to disallow (since we've determined that it is
+unimplementable in general - 'First and 'Last are just confusing).
+
+****************************************************************
+
+From: Robert Dewar
+Date: Friday, October 1, 2010 6:30 PM
+
+> The set constraint proposal includes a check that each value of the
+> set belongs to the range of the parent subtype. (It also doesn't
+> syntactically allow the above, of course.) So the intent there is that
+> something like this would raise Constraint_Error (and in this case
+> [and most other cases], the compiler would issue a warning that it would always do that).
+
+I think the right thing to do here is simply to say that for a predicate to be
+static, it has to have a static range, and all elements of the set expression
+have to be static and lie in this range, otherwise it is not static.
+
+> That has the advantage that we don't have to worry about non-static
+> ranges, in that they get checked and then can be ignored (either the
+> subtype raises Constraint_Error, in which case no one can use it, or
+> it is OK to treat it as static). This is similar to what happens for
+> ranges themselves: only the "last" range has any semantic effect other
+> than in the declaration of the subtype.
+
+I do not like the idea of a separate aspect name for the static stuff.
+It is unnecessary, adds complication, and is inconsistent with the treatment of
+static expressions elsewhere in the language.
+
+> That way, if we have:
+>
+> subtype W is range Function_returning_I .. U;
+> subtype V is W with Set_Predicate => V in (A | U);
+>
+> V also raises Constraint_Error or works as if it is static.
+
+I really think this is unnecessary
+
+>> Well lots of aspects affect legality
+>>
+>> type X is new Integer with
+>> Size => 3;
+>>
+>> is illegal
+>
+> That's not what I meant; I'm talking about things other than aspects.
+> There are few aspects that affect the legality of anything other than
+> other aspects.
+
+But there are cases, and I really think this is not a big deal, and not worth
+adding more complexity of it.
+
+> This is definitely true. But just because Ada does something wrong
+> currently doesn't mean we have to repeat that in new features. (For
+> instance, we require matching rather than ignore the subtypes for new
+> features in
+> renaming.)
+
+I disagree this is done wrong now, and I think consistency is more important
+than a dubious claim that you are inconsistenyt because the language is wrong
+now.
+
+> Correct of course; but this particular case is a major problem (at
+> least it has been in my code) because it is common to want to write a
+> representation clause like R'Size use Component_1'Size +
+> Component_2'Size, and this is illegal if either of the components are
+> composite. I usually end up using the literal value and adding some
+> code somewhere "if<literal> /= Component_1'Size + Component_2'Size
+> then raise Program_Error; end if;". This is silly at the best.
+
+I can't see this as a major problem (in 15 years, no one has complained about
+this in the context of GNAT, and people complain about anything they don't like
+very freely). I certainly don't find it an issue in my code. I don't find that a
+common way to write a rep clause at all, on the contrary it seems to be assuming
+all kinds of target dependent stuff about alignment etc.
+
+> So I don't have much sympathy for using the existence of a major
+> annoyance in Ada to justify introducing another similar maintenance hazard.
+
+For me this does not even rise to the level of minor annoyance, let alone major
+annoyance.
+
+>>> One would presume to extend Tucker's "with predicate" idea for
+>>> generic formals to handle the different kinds as well, reducing the
+>>> need for Program_Error.
+>>
+>> Seems like an unnecessary complication to me in practice, and I think
+>> it will just be a nuisance. Is it really worth this nuisance just to
+>> deal with the marginal obscure case of using 'First and 'Last?
+
+> But note that the major use isn't for 'First and 'Last, it is in
+> (dis)allowing the use of the subtype in array indexes and slices.
+> That's both more likely to happen and much more important to disallow
+> (since we've determined that it is unimplementable in general - 'First
+> and 'Last are just confusing).
+
+I see the use of enumeration subtypes as array indexes as being pretty unusual
+in the context of predicates. I don't see this again as worth worrying about.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Friday, October 1, 2010 6:36 PM
+
+> The whole idea of static predicates is a new one and not really
+> related to the existing proposal (it's much more related to set
+> constraints than predicates). The only reason we didn't approve
+> AI05-0153-1 in Valencia was that we didn't agree on the wording for
+> the new restrictions on composite predicate expressions. So I would
+> prefer to have the existing AI reflect the decisions of that meeting
+> exactly; and have a separate alternative with the more complex
+> proposal that is now being crafted here. That way, we can see if it really is more complex or not.
+
+I see no point in this extra level of work, we know we need the static
+predicates here (for GNAT, the approval or non-approval of this feature in the
+official standard will only affect the operation of the equivalent of the
+-pedantic mode, so it is not a big deal). To me the proposal is useless without
+the static predicates for cases, so why bother preparing or discussing a useless
+proposal. Is there anyone who thinks that we do NOT need these things to work in
+case statements?
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Friday, October 1, 2010 10:07 PM
+
+> > The whole idea of static predicates is a new one and not really
+> > related to the existing proposal (it's much more related to set
+> > constraints than predicates). The only reason we didn't approve
+> > AI05-0153-1 in Valencia was that we didn't agree on the wording for
+> > the new restrictions on composite predicate expressions. So I would
+> > prefer to have the existing AI reflect the decisions of that meeting
+> > exactly; and have a separate alternative with the more complex
+> > proposal that is now being crafted here. That way, we can see if it
+> > really is more complex or not.
+>
+> I see no point in this extra level of work,
+
+There is no significant extra work involved in this, given that all I'm asking
+is to keep the Valencia proposal around intact.
+
+> ... we know we need
+> the static predicates here (for GNAT, the approval or non-approval of
+> this feature in the official standard will only affect the operation
+> of the equivalent of the -pedantic mode, so it is not a big deal). To
+> me the proposal is useless without the static predicates for cases, so
+> why bother preparing or discussing a useless proposal. Is there anyone
+> who thinks that we do NOT need these things to work in case
+> statements?
+
+The entire predicate proposal has been very controversial, just barely getting
+enough support to survive. Almost everybody has seriously considered voting
+against it at some point or other (including me and Bob). If the only version in
+existence is one loaded down with bells and whistles, it is much more likely to
+be rejected.
+
+And yes, I do view the set constraint as a bell/whistle on this proposal. (I
+realize that your mileage differs greatly on that.) The problems that I have
+that I hope to solve all have to do with subtypes of a composite types, which
+this added feature has little to do with. The only reason that predicates are
+allowed on scalar types at all is because we would otherwise have generic
+contract problems with formal private types (they cause a lot of problems where
+reasonable things can't be implemented).
+
+So while I agree with you that if set constraints are allowed in some form, they
+have to work in case statements and for loops, I don't agree with you that they
+have to be included in a predicate proposal.
+
+In any case, the entire ARG will need to weigh in on this at the next meeting;
+there is little point in just two of us discussing and completely disagreeing on
+this point.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Friday, October 1, 2010 10:19 PM
+
+> And yes, I do view the set constraint as a bell/whistle on this
+> proposal. (I realize that your mileage differs greatly on that.) The
+> problems that I have that I hope to solve all have to do with subtypes
+> of a composite types, which this added feature has little to do with.
+> The only reason that predicates are allowed on scalar types at all is
+> because we would otherwise have generic contract problems with formal
+> private types (they cause a lot of problems where reasonable things can't be
+> implemented).
+
+I don't believe that for one moment, having talked to several people involved in
+the diccussion. It is clear that there is considerable value in having
+predicates for scalars. Indeed, virtually all the uses I see for predicates are
+for scalars (though by no means are all in the static category). I do see some
+utility for composites, but far less than for scalars.
+
+> So while I agree with you that if set constraints are allowed in some
+> form, they have to work in case statements and for loops, I don't
+> agree with you that they have to be included in a predicate proposal.
+
+You still are transparently following an agenda of trying to get in your set
+constraint proposal, but to me that has no hope at this stage, and I think it is
+a bad idea to try to cripple the predicate proposal in a continuing attempt to
+push the idea of the set constraint proposal.
+
+> In any case, the entire ARG will need to weigh in on this at the next
+> meeting; there is little point in just two of us discussing and
+> completely disagreeing on this point.
+
+Well by the time the ARG discusses this, we will have some more experience with
+actual use, since the Ada 2012 prevue that we will release shortly will have a
+full implementation of predicates including an implementation of static
+predicates. The main purpose of the static predicates is surely for case
+statements, but I will try to get in the loops if I can (note you can always do
+the loops yourself, but you can't do the case statements yourself without losing
+the essential completeness check.
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Friday, October 1, 2010 10:33 PM
+
+...
+> > That has the advantage that we don't have to worry about non-static
+> > ranges, in that they get checked and then can be ignored (either the
+> > subtype raises Constraint_Error, in which case no one can use it, or
+> > it is OK to treat it as static). This is similar to what happens for
+> > ranges themselves: only the "last" range has any semantic effect
+> > other than in the declaration of the subtype.
+>
+> I do not like the idea of a separate aspect name for the static stuff.
+> It is unnecessary, adds complication, and is inconsistent with the
+> treatment of static expressions elsewhere in the language.
+
+So what? This concept has nothing whatsoever to do with static expressions.
+
+In particular, the expression of a predicate can never be static, because the
+current instance of the subtype is never static. (How could it be? The actual
+object being tested might be a variable.)
+
+I can imagine defining this somehow in terms of static expressions, but in any
+case it is a new concept. That being said, there is nothing in particular to be
+consistent with.
+
+...
+> > That's not what I meant; I'm talking about things other than aspects.
+> > There are few aspects that affect the legality of anything other
+> > than other aspects.
+>
+> But there are cases, and I really think this is not a big deal, and
+> not worth adding more complexity of it.
+
+It used to be a huge deal to Pascal with the Rational compiler. Whether it would
+be in this case (or whether we ought to care), I can't say. But I'm still
+sensitive to those concerns.
+
+> > This is definitely true. But just because Ada does something wrong
+> > currently doesn't mean we have to repeat that in new features. (For
+> > instance, we require matching rather than ignore the subtypes for
+> > new features in
+> > renaming.)
+>
+> I disagree this is done wrong now, and I think consistency is more
+> important than a dubious claim that you are inconsistenyt because the
+> language is wrong now.
+
+But there is nothing here to be consistent with. The closest thing to be
+consistent with here is range constraints; in order to do that you need the
+entire set constraint mechanism as outlined in AI05-0153-2. I think we all agree
+we are not going to do that; therefore any solution that we chose is going to be
+very inconsistent with the rest of the language. That's especially true if we
+insist on your "all static ancestors" rule - which is nothing like any other
+subtype in the language. (BTW, such a rule would mean that you couldn't define a
+set of any generic formal discrete type. Maybe not a big deal, but that to me
+seems inconsistent with the rest of the language.) Predicates in general are
+also very inconsistent with the rest of language in that they don't allow use as
+array indexes and the like.
+
+So I view this as an entirely new feature that pretty much has to be very
+inconsistent with the rest of the language. At this point, why add in
+maintenance hazards and readability problems??
+
+> > Correct of course; but this particular case is a major problem (at
+> > least it has been in my code) because it is common to want to write
+> > a representation clause like R'Size use Component_1'Size +
+> > Component_2'Size, and this is illegal if either of the components
+> > are composite. I usually end up using the literal value and adding
+> > some code somewhere "if<literal> /= Component_1'Size +
+> > Component_2'Size then raise Program_Error; end if;". This is silly at the best.
+>
+> I can't see this as a major problem (in 15 years, no one has
+> complained about this in the context of GNAT, and people complain
+> about anything they don't like very freely). I certainly don't find it
+> an issue in my code. I don't find that a common way to write a rep
+> clause at all, on the contrary it seems to be assuming all kinds of
+> target dependent stuff about alignment etc.
+
+It's probably more correct that it is assuming all kinds of
+*compiler-dependent* stuff, in that this works fine on all existing (and the
+uncompleted ones as well) Janus/Ada compilers. I can easily believe that other
+compilers do something different. I *know* that I have tried to write code like
+this many times (including in Claw) and it gets rejected. I'm quite surprised
+that you've never had anyone complain about it, given I've seen others gripe
+about this problem on comp.lang.ada. I suspect, though, that most everybody
+gripes and then replaces the code by something less portable; it's not the sort
+of thing that a compiler writer can do anything about.
+
+...
+> > But note that the major use isn't for 'First and 'Last, it is in
+> > (dis)allowing the use of the subtype in array indexes and slices.
+> > That's both more likely to happen and much more importantto disallow
+> > (since we've determined that it is unimplementable in general - 'First
+> > and 'Last are just confusing).
+>
+> I see the use of enumeration subtypes as array indexes as being pretty
+> unusual in the context of predicates. I don't see this again as worth
+> worrying about.
+
+It *has* to be worried about. It's not possible to implement slices in general
+for such subtypes (consider an array of limited components; there is no way to
+"close up the gaps" in the slice, and distributed overhead to handle such cases
+in unacceptable - remember that the slice can be passed as a parameter to some
+other routine). For direct uses of such subtypes, the uses are statically
+illegal in slices, array indexing, and the like. The problem is, what if someone
+uses a formal discrete subtype in a slice? If it has a predicate, it has to be
+disallowed somehow. But using an assume-the-worst rule would be wildly
+incompatible (that would disallow all such slices in generic bodies). Thus we
+proposed a runtime check that raises Program_Error; all Tucker is proposing is
+to add some additional syntax to allow us to use the assume-the-worst rule
+without introducing compatibility problems.
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Friday, October 1, 2010 11:53 PM
+
+...
+> > So while I agree with you that if set constraints are allowed in
+> > some form, they have to work in case statements and for loops, I
+> > don't agree with you that they have to be included in a predicate
+> proposal.
+>
+> You still are transparently following an agenda of trying to get in
+> your set constraint proposal, but to me that has no hope at this
+> stage, and I think it is a bad idea to try to cripple the predicate
+> proposal in a continuing attempt to push the idea of the set
+> constraint proposal.
+
+I'm certainly not doing that on purpose. But what you are asking to be added to
+the language is semantically very similar to the set constraint proposal. I
+certainly don't care that much about the exact name it is given or the exact
+syntax. But it is going to need to have essentially the same set of rules as was
+given in that old proposal; some of those can be shared with "regular"
+predicates, but not all can (because of the added capabilities, of course). It
+isn't possible to add "static predicates" to the language and have them work in
+case statements and for loops without adding a lot of new text and probably a
+few new concepts as well.
+
+If that is "trying to get in your set constraint proposal", I suppose then I am
+guilty. But I don't believe that there is any sane way to add "set predicates"
+or "static predicates" or whatever you want to call it to the language without
+adopting many of the rules from the "set constraint" proposal. I had long since
+given up on set constraints, except that you keep insisting that we have to have
+them (in a different syntax, but with essentially the same semantics as
+originally proposed). I'm not "trying to get" anything in here -- I can surely
+live without this by any name. But if we do have it, then we're going to be
+adding some form of set constraints (although surely not by that name) -- no
+other result is possible. That's simply a pragmatic judgment, not some attempt
+at a hidden agenda.
+
+What I *can't* live with is adding maintenance and readability problems to the
+language in the guise of consistency, particularly when this is an entirely new
+feature that is already very inconsistent with existing subtypes. (And some of
+the rules you are proposing makes it more inconsistent with existing subtypes.)
+Perhaps I'm alone on that, perhaps not; we'll need to get input from other ARG
+members to figure that out. Nothing that you or I say here is going to be the
+last word on this subject -- and I'm not sure that further discussion here is
+going to add anything.
+
+****************************************************************
+
+From: Tucker Taft
+Date: Saturday, October 2, 2010 2:25 PM
+
+I suspect that some people are more friendly to the (potentially-static) subtype
+predicate approach in that it piggy backs on the aspect specification syntax.
+You are almost certainly right that getting static predicates to work may
+require many of the same things that the set constraints would have required,
+but avoiding adding a new constraint syntax is a significant advantage for
+predicates, at least to some people (including me, for what it is worth), even
+if it ends up requiring more words in the RM. Somehow additional syntax "weighs"
+a lot more than additional RM words for most people.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Saturday, October 2, 2010 3:19 PM
+
+Absolutely true! And indeed having several different syntaxes for what is to the
+programmer essentially the same thing is a mistake, even if in the language
+lawyer realm it makes things "cleaner". to me even distinguishing between
+invariants and predicates is a big mistake which will cause a lot of confusion.
+I would have used the same syntax for both, and simply made whether or not they
+were applied to private types be the distinguishing factor (and having the
+inside/outside semantics for predicates on private types, which makes perfect
+sense given that private types look quite different inside, and then you would
+put a predicate/whatever on the full type if you want checking inside.
+
+Anyway, I guess the unfortunate duplication of concepts in invariants/predicates
+is a done deal, too bad, but let's not exacerbate this by trying to have
+different syntax for static and non-static predicates.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Saturday, October 2, 2010 3:47 PM
+
+In this note, I want to specifically address the issue of looping through
+predicated types with a syntax like
+
+ for J in subtype loop
+
+It seems like we have three possibilities
+
+a) allow it always, the official semantics could be
+
+ for J in subtype'base'range loop
+ if predicate(J) then
+ body
+ end if
+ end loop
+
+ with specific implementation permission allowing optimization.
+
+ probably general implementation permission apply to predicates
+ and invariants in general should be something like
+
+ If the compiler can determine the returned result of evaluating
+ a predicate at compile time, or if the result is not needed,
+ then the evaluation of the predicate or invariant expression
+ can be omitted (even if there are side effects).
+
+b) forbid it entirely
+
+c) allow it only for static predicates
+
+I can live with b, since I don't think it's terribly useful, but on the other
+hand there are some who think it IS really useful (Randy in particular), and it
+does help ease generic contract concerns (one less case for warnings/exception
+when an error message wold violate the generic contract model).
+
+I don't really like c), since it is weird to have staticness control the
+validity of a loop (case statements are a different matter, there we are used to
+staticness being an issue).
+
+Furthermore, defining the semantics so it just covers case
+c) is a peculiar excercise. The easiest way of defining the semantics is with
+the bogus loop that you would use if you choose approach a).
+
+So I would go with a), it's no harder to implement than c.
+
+Note that an efficient implementation of c) is not easy!
+I can think of three approaches
+
+a) do the loop through subtype'first .. subtype'last. This can obviously be
+ disastrously inefficient in time for a case like
+
+ subtype Integer_Extremes is Integer with
+ predicate => Integer_Extremes in Integer'First | Integer'Last;
+
+b) build an array of valid values and iterate through that. This can be
+ disastrously inefficient in space in a case like:
+
+ subtype Integer_Non_Zero is Integer with
+ predicate => Integer_Non_Zero in
+ Integer'First .. -1 | +1 .. Integer'Last;
+
+c) use a case statement like
+
+ subtype Consonants is Character with
+ predicate => Consonants in
+ 'B' .. 'D' |
+ 'F' .. 'H' |
+ 'J' .. 'N' |
+ 'P' .. 'T' |
+ 'V' .. 'Z';
+
+ for J in Consonants loop
+ body
+ end loop
+
+ translates to
+
+ declare
+ J : Character := 'B';
+ begin
+ loop
+ body
+
+ case J is
+ when 'D' => J := 'F';
+ when 'H' => J := 'J';
+ when 'N' => J := 'P';
+ when 'T' => J := 'V';
+ when 'Z' => exit;
+ when others
+ J := Character'Succ (J);
+ end case;
+ end loop;
+ end;
+
+A bit complicated, but takes advantage of the (presumably complex and efficient
+and there already) code for generating efficient code for case statements.
+
+One final thought, it is odd to allow
+
+ subtype R is Character with
+ predicate => R in 'A' | 'F' | 'W' .. 'Y';
+
+ for J in R loop ...
+
+and to disallow
+
+ for J in 'A' | 'F' | 'W' .. 'Y' loop ...
+
+Obviously it is no harder to implement one than the other, so perhaps we should
+give some thought to allowing the more general loop format?
+ when Z => I := Q;
+
+****************************************************************
+
+From: Robert Dewar
+Date: Saturday, October 2, 2010 3:50 PM
+
+Randy notes that the predicate expression is not static since it is of the form
+
+ type in bla bla
+
+yes, well of course type is not static but that's language lawyerism running
+amok if you make too much of it, and certainly claiming this makes things
+completely different from normal static expressions is unnecessary at an
+informal level.
+
+At an informal level, if you just said that a predicate to be static must be of
+the form of a set expression and must be static to use in a case statement, then
+informally anyone would know what you meant. Yes, you need to work harder in the
+RM to describe this, but simplicity of description in the RM is a very
+unimportant criterion in the total scheme of things, and we certainly don't want
+to complicate the informal understanding of the language in an attempt to
+simplify the (already unreadable in any case for most programmers) RM.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Saturday, October 2, 2010 3:54 PM
+
+So far I have thought of limiting it to set membership form, but the example I
+wrote in previous mail definitely lead one to at least wonder about
+generalizing:
+
+> subtype Integer_Non_Zero is Integer with
+> predicate => Integer_Non_Zero in
+> Integer'First .. -1 | +1 .. Integer'Last;
+
+Contrast with
+
+> subtype Integer_Non_Zero is Integer with
+> predicate => Integer_Non_Zero /= 0;
+
+The latter is easier to write, but would not qualify as static if we insist on
+set forms
+
+****************************************************************
+
+From: Robert Dewar
+Date: Saturday, October 2, 2010 4:00 PM
+
+Do we allow
+
+ subtype X is Integer with
+ predicate =>
+ x in 1 .. 10 | 7 .. 15;
+
+I think the easy answer is yes, here is an example showing it is helpful to
+allow this kind of overlap
+
+ type European_Countries is (England, Monaco, France, ...
+
+ subtype Eurozone is European_Countries with
+ predicate => Eurozone in Monaco | France ...
+
+ subtype EEC is European_Countries with Predicate
+ predicate => EEC in England | France ....
+
+It seems nice to be able to write
+
+ subtype Euro_Friendly is European_Countries with
+ predicate Euro_Friendly in Eurozone | EEC;
+
+to disallow this would make maintenance painful, since one would have to know
+about the overlap in writing the declaration for Euro_Friendly.
+
+****************************************************************
+
+From: Tucker Taft
+Date: Sunday, October 3, 2010 12:53 PM
+
+> So far I have thought of limiting it to set membership form, but the example I
+> wrote in previous mail definitely lead one to at least wonder about
+> generalizing:
+...
+
+We went around already on the problem with staticness and full coverage when you
+have general static predicates such as:
+
+ subtype Very_Even is Long_Long_Integer with predicate
+ Very_Even mod 2**60 = 0;
+
+Use of such subtypes, either as case statement labels, or as the subtype of the
+case expression, would be painful, since determining full coverage would be
+difficult. We could require an "others" alternative, as we do for universal
+integer case expressions now, but that would lose the benefit of full coverage.
+We could require the "others" in just some cases, e.g. whenever it is a form we
+consider too "hard" to enumerate.
+
+Use of "mod" or "rem" by a large number is painful, unless you recognize it
+specially, as would be use of "and" and "xor" with a large modular type,
+probably. Use of exponentiation with a modular type would also be painful. I
+suppose we could set some arbitrary limit on the underlying contiguous range of
+the subtype, and if it is larger than 1000, say, then we require the "others."
+Sounds pretty groddy, though the limit of 200 for static strings is a bit of a
+precedent for groddy rules relating to staticness.
+
+****************************************************************
+
+From: Tucker Taft
+Date: Sunday, October 3, 2010 1:04 PM
+
+> Do we allow
+>
+> subtype X is Integer with
+> predicate =>
+> x in 1 .. 10 | 7 .. 15;
+>
+> I think the easy answer is yes, here is an example showing it is
+> helpful to allow this kind of overlap
+...
+
+I certainly agree with this. I can't see any benefit in requiring
+non-overlapping ranges for predicates, if the corresponding membership test
+would be static. In general, I hope the rule would be based on the staticness of
+the corresponding membership test, if the subtype name were replaced with a
+static expression.
+
+I suppose one generalization that would still avoid the complexities of "x mod
+2**60 = 0" would be to require that the subtype name must appear directly as the
+operand of a membership or relational/equality operator, i.e. with no arithmetic
+operator applied to it first. Hence "X mod 2**60 /= 0" as a predicate would
+*not* result in a static subtype, but "X /= (3**25 mod 2**60)" would be fine. We
+will have to make some statement about the subtype name appearing alone in the
+membership test (since "(X mod 2**60) in 0..0" isn't better than "X mod 2**60 =
+0"), so having said the subtype name must appear alone, we can perhaps
+generalize to allow other relational/equality operators as well.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Sunday, October 3, 2010 1:27 PM
+
+> We went around already on the problem with staticness and full
+> coverage when you have general static predicates such as:
+>
+> subtype Very_Even is Long_Long_Integer with predicate
+> Very_Even mod 2**60 = 0;
+...
+
+OK, let's limit it to set membership, that gets the common cases, and is easy to
+describe and reasonably easy to implement (just wrote many hundreds of lines of
+code for static predicates, but it's all straight forward, and I included the
+loop case :-))
+
+****************************************************************
+
+From: Robert Dewar
+Date: Sunday, October 3, 2010 1:35 PM
+
+> I suppose one generalization that would still avoid the complexities
+...
+
+I would not generalize, I would say that static predicates must be of the form
+
+ subtype_IDENTIFIER in static_MEMBERSHIP_CHOICE_LIST
+
+ MEMBERSHIP_CHOICE_LIST ::=
+ MEMBERSHIP_CHOICE {'|' MEMBERSHIP CHOICE}
+
+ MEMBERSHIP_CHOICE ::=
+ CHOICE_EXPRESSION | RANGE | SUBTYPE_MARK
+
+where static here means that
+
+CHOICE_EXPRESSION is a static epression
+RANGE is a static range
+SUBTYPE_MARK references a static subtype without a predicate, or a subtype with
+a static predicate.
+
+In addition, I would require that to be static
+
+None of the static_MEMBERSHIP_CHOICE_LIST entries an be outside the range of the
+subtype
+
+The subtype itself must have a static range
+
+The subtype must not inherit predicates (or have more than one predicate, since
+we allow multiple predicate pragmas in GNAT) (*)
+
+This limited form covers the important case of what Randy calls set predicates,
+which is 99% of the useful usage of static predicates. Let's not over-complicate
+the proposal to death by trying to go from implementable reasonable good, to
+unimplemented over-complex best.
+
+After all lost of things are not static that should be (my favorite peeve in
+this area is that 'Size should always be static if you have given an explicit
+static Size value in the program).
+
+****************************************************************
+
+From: Robert Dewar
+Date: Sunday, October 3, 2010 2:34 PM
+
+> I certainly agree with this. I can't see any benefit in requiring
+> non-overlapping ranges for predicates, if the corresponding membership
+> test would be static.
+> In general, I hope the rule would be based on the staticness of the
+> corresponding membership test, if the subtype name were replaced with
+> a static expression.
+
+I think that criterion is met with the
+exception of checking the range against
+the range of the subtype. We could of
+course just ignore it this is cases like
+
+ type C is (A,B,C,D,E,F,G,H,I,J);
+
+ subtype K is C range C .. H with
+ Predicate => K in B .. D | H | J;
+
+I consider this non-static because of the B that is outside the raneg C .. H. Of
+course giving a range as well as a list in the predicate is unusual anyway (I
+considered the possibility of the mere presence of a range making the predicate
+non-static, but decided to allow a static range).
+
+I would not mind just excluding B in a case like this, not a big deal.
+
+Of course it would be nice to have warnings as to why this is non-static.
+
+I am thinking of implementing a pragma Static which would check staticness and
+be usable in the other cases randy worries about, it's main purpose would be to
+check at the point of definition, and allow you to give clearer diagnostics as
+to why something is not static, but no big deal.
+
+Back to overlap, allowing overlap here makes good sense to me, but note we don't
+allow it in case statements themselves:
+
+> 1. procedure w is
+> 2. type R is (A, B, C, D, E, F);
+> 3. RV : R;
+> 4. begin
+> 5. case RV is
+> 6. when A => null;
+> 7. when B .. D | C .. E => null;
+> |
+> >>> duplication of choice value at line 7
+>
+> 8. when F => null;
+> 9. end case;
+> 10. end w;
+
+So it's a little odd that now if I define a static predicate with this exact
+same set of values spelled the same way, the case statement WILL work with the
+name of that static predicate.
+
+Note that my argument in favor of allowing overlap is just as applicable to case
+statements
+
+ when Eurozone | EEC =>
+
+would be illegal now, and for the same reasons I gave before this would be
+annoying.
+
+Still giving names to such choices, which is now possible, is SUCH an
+improvement that I don't mind too much pushing people in that direction :-)
+
+****************************************************************
+
+From: Tucker Taft
+Date: Sunday, October 3, 2010 3:05 PM
+
+I'm curious why you don't think it is reasonable to generalize to all equality/
+relational operators. X in 1..10 is essentially equivalent to X >= 1 and X <=
+10, so it seems odd to specifically require membership. And as you pointed out,
+"X /= 0" is certainly more readable and natural than X in blah'first .. -1 | +1
+.. blah'last. There are already restrictions in the use of discriminants that
+they must be used alone rather than as part of a larger expression, so this
+feels somewhat in the same ballpark.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Sunday, October 3, 2010 4:36 PM
+
+I just think that fully analyzing expressions like
+
+ (X >= 1 and <= 10) or ... and ..
+
+will be a bit of an implementation nightmare ...
+I think it is a good idea to keep things simple at first, and then if we find we
+really need more generalization, OK, we can look at the effort required.
+
+Just doing the set predicates is a LOT of work!
+
+I am also concerned that endless arguments and discussion over what should or
+should not be static will be a messy discussion that will drag things out at a
+stage where such dragging is not welcome. If you burden the predicates feature
+with too many bells and whistles you risk killing it.
+
+BTW here is some output from GNAT in its current state:
+
+> 1. procedure Static_Predicates is
+>> 2. type a is (B, C, D, E, F, G, H, I, J, K, L, M, N);
+>> 3. subtype s1 is a with
+>> 4. Predicate => S1 in C | J | E .. F;
+>> 5. subtype s2 is a with
+>> 6. Predicate => S2 in L .. N | S1 | D | L .. M;
+>> 7.
+>> 8. V1 : s1;
+>> 9. V2 : s2;
+>> 10.
+>> 11. begin
+>> 12. case V1 is
+>> 13. when B => null;
+>> 14. when D => null;
+>> 15. when G .. I => null;
+>> 16. when K .. N => null;
+>> 17. when S1 => null;
+>> 18. end case;
+>> 19.
+>> 20. case V2 is -- I missing
+>> |
+>> >>> missing case value: "I"
+>>
+>> 21. when B => null;
+>> 22. when S2 => null;
+>> 23. when G .. H => null;
+>> 24. when J .. K => null; -- duplicates J
+>> |
+>> >>> duplication of choice value at line 22
+>>
+>> 25. end case;
+>> 26. end;
+
+****************************************************************
+
+From: Robert Dewar
+Date: Monday, October 4, 2010 11:27 PM
+
+I just found an interesting infinite loop in my implementation, and I wondered
+whether it might also be an infinite loop in the description?
+
+ type R is new Integer with
+ R in 1 .. 7 | 10 .. 12;
+
+The implementation (and description?) of membership tests for predicated types
+includes a call to the predicate, so that sounds a bit recursive :-) Easily
+fixed with a special kludge test in the implementation of course!
+
+****************************************************************
+
+From: Steve Baird
+Date: Monday, October 4, 2010 12:09 PM
+
+I don't think there is any problem here with recursion.
+
+Recall that the predicate for a base subtype is always True, and that a
+predicate is associated with a subtype, not with a type.
+
+In this example,
+ R in 1..7 | 10..17
+is (if you don't mind some fast-and-loose name resolution) semantically
+equivalent to
+
+ R in R'Base range 1.. 7 | R'Base range 10 .. 17
+
+, where the "R" in the two occurrences of R'Base refers to R, not to he current
+instance of R (as opposed to the first use of "R" in the predicate expression,
+which refers to the current instance).
+
+There is a freezing issue here (the predicate expression includes static
+expressions of type R'Base). This has been discussed internally at AdaCore.
+
+Steve Baird wrote:
+> I think we need a freezing rule something like
+>
+> At the place where a subtype is frozen, its predicate expression
+> (including any inherited predicate expressions) causes freezing.
+>
+> and then we also need to add predicate expressions to the
+> special-exemption list of 13.14(8/1):
+>
+> An object name or nonstatic expression causes freezing where it
+> occurs, unless the name or expression is part of a default_expression,
+> a default_name, or a per-object expression of a component's
+> constraint, in which case, the freezing occurs later as part of
+> another construct.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Monday, October 4, 2010 12:48 PM
+
+> In this example,
+> R in 1..7 | 10..17
+> is (if you don't mind some fast-and-loose name resolution)
+> semantically equivalent to
+>
+> R in R'Base range 1.. 7 | R'Base range 10 .. 17
+
+Are you saying that if I have a predicated subtype R then
+
+ RX : R;
+
+ if RX in R ..
+
+checks the subtype predicate
+
+but if RX in 1 .. 7
+
+does not check the subtype predicate (right now I check the range and the
+predicate in such a case, but of course that is easily changed).
+
+what about
+
+ if RX in R'(1) .. R'(7);
+
+same thing?
+
+****************************************************************
+
+From: Steve Baird
+Date: Monday, October 4, 2010 12:59 PM
+
+> Are you saying that if I have a predicated subtype R then
+>
+> RX : R;
+>
+> if RX in R ..
+>
+> checks the subtype predicate
+>
+> but if RX in 1 .. 7
+>
+> does not check the subtype predicate (right now I check the range and
+> the predicate in such a case, but of course that is easily changed).
+>
+
+Yes, that is my reading of the AI.
+
+> what about
+>
+> if RX in R'(1) .. R'(7);
+>
+> same thing?
+
+Here you get predicate checks on 1 and 7 (because of
+the subtype conversion associated with a qualified
+expression) =, but not on Rx.
+
+You might get a predicate check on
+
+ if Rx in R range 1 ,, 7
+
+, or you might not because of the implementation
+permission (which applies because the subtype of Rx is R).
+
+At least that's my interpretation.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Monday, October 4, 2010 1:00 PM
+
+OK, well I can easily fix this, anyone else care to comment on this?
+
+****************************************************************
+
+From: Tucker Taft
+Date: Monday, October 4, 2010 1:25 PM
+
+I agree with Steve's interpretation.
+A range by itself has a *type* but does not have a *subtype*, or at least the RM
+never mentions the subtype of a range.
+
+A subtype_indication with a range constraint clearly is defining a subrange of a
+subtype, but a "range" by itself is defining a subrange of a type, independent
+of the "subtype" of the bounds of the range. Actually, *values* of an
+elementary type don't really have subtypes, only types. An *object* of an
+elementary type has a subtype, but the bounds of a range are values, not
+objects.
+
+****************************************************************
+
+From: Steve Baird
+Date: Monday, October 4, 2010 2:53 PM
+
+> You might get a predicate check on'
+>
+> if Rx in R range 1 ,, 7
+>
+> , or you might not because of the implementation permission (which
+> applies because the subtype of Rx is R).
+>
+
+I said this, and I believe that this is the intent, but (upon looking at the AI
+again) I don't think the wording of the AI correctly captures this.
+
+The AI says:
+ A predicate check may be omitted if the subtype with the predicate
+ statically matches the nominal subtype of the value being checked.
+
+The subtypes R and "R range 1 .. 7" have the same predicate, but they certainly
+do not statically match.
+
+The definition of "statically compatible" needs to take predicates into account.
+I don't remember whether this point has already been discussed, but the point
+holds in any case.
+
+Assuming that "statically compatible" is defined correctly, one approach would
+be to use that notion instead of "statically matches" in the implementation
+permission.
+
+This would be an improvement, but it still wouldn't work in the case in
+question. The compatibility relationship holds in the wrong direction in this
+particular example.
+
+I think we need to capture the notion of two subtypes having the same predicate
+and of one having a predicate which implies the predicate of the other (because
+the predicate of the former is a conjunction of the predicate of the latter with
+other predicates).
+
+The general idea is that in deciding whether it is ok to eliminate a predicate
+check, an implementation should be allowed to assume that
+ 1) the predicate is "well-behaved" - given the same argument twice,
+ it returns the same answer and it returns a Boolean result
+ (as opposed to raising an exception, failing to terminate, etc.)
+ for any argument in the basetype.
+ 2) the value of an object satisfies the predicate of the subtype
+ of the object (this assumption may be false for, say,
+ uninitialized variables, but that's ok).
+
+One approach would be to define the implementation permission explicitly in
+these terms.
+
+The current wording is not permissive enough and requires checks in cases which
+meet these criteria. A performance hit associated with requiring unneeded
+predicate checks would not be good.
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Monday, October 4, 2010 3:25 PM
+
+...
+> 1) the predicate is "well-behaved" - given the same argument twice,
+> it returns the same answer and it returns a Boolean result
+> (as opposed to raising an exception, failing to terminate, etc.)
+> for any argument in the basetype.
+> 2) the value of an object satisfies the predicate of the subtype
+> of the object (this assumption may be false for, say,
+> uninitialized variables, but that's ok).
+
+I don't think this is OK as you have written it. It would be OK to say "if the
+value of an object is known to be valid, then the value of the object satisfies
+the predicate".
+
+Another way to put it is that "if the compiler can assume the value is in range,
+it can also assume that the value satisifies the predicate". We definitely don't
+want to be able to elimimate predicate changes in cases where it is not allowed
+to eliminate range checks.
+
+I suspect that both of the above are the same as assuming (1) [since a valid
+value must have been checked at some previous point], so my feeling is that it
+is the only assumption needed.
+
+Or to put it another way: We really do not want to restart all of the arguments
+about when you can assume validity of objects! (Or rework those rules, either.)
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Monday, October 4, 2010 4:01 PM
+
+> a) allow it always, the official semantics could be
+...
+> b) forbid it entirely
+>
+> c) allow it only for static predicates
+>
+> I can live with b, since I don't think it's terribly useful, but on
+> the other hand there are some who think it IS really useful (Randy in
+> particular), and it does help ease generic contract concerns (one less
+> case for warnings/exception when an error message wold violate the
+> generic contract model).
+>
+> I don't really like c), since it is weird to have staticness control
+> the validity of a loop (case statements are a different matter, there
+> we are used to staticness being an issue).
+
+I don't think (a) is practical in the general case, because such a loop could
+take literally forever to run, even for a small set of values. In particular,
+consider the 64-bit type (based on the one Tucker noted):
+
+ function Is_Very_Even (V : in Long_Long_Integer) return Boolean is
+ begin
+ return V mod 2**60 = 0;
+ end Is_Very_Even;
+
+ subtype Very_Even is Long_Long_Integer with predicate
+ Is_Very_Even (Very_Even);
+
+If the function is declared such that the body isn't known to the compiler, then
+there is no way to avoid iterating over the entire 64 bit integer space, calling
+the function each time. That's going to take a long time!
+
+Even if this somehow worked on a particular compiler, it probably wouldn't be
+portable (as there could be no requirement for other compilers to come up with
+such an optimization). As such, using loops other than in the static set
+predicate case is dangerous (even though the definition is clear, practically it
+may not work). This was the reason that we made loops illegal for the general
+case of predicates.
+
+> Furthermore, defining the semantics so it just covers case
+> c) is a peculiar excercise. The easiest way of defining the semantics
+> is with the bogus loop that you would use if you choose approach a).
+
+Huh? For a static set predicate, the solution is to define the set of values of
+the subtype. This also properly defines the set of values for the case statement
+(and probably other cases that I can't remember right now). That of course isn't
+possible for the general predicate case.
+
+But in order for that to work, there needs to be a clear distinction between the
+two cases. I would prefer that distinction is one that programmers are required
+to declare in some way (as it avoids maintenance headaches caused by the
+semantics changing).
+
+> So I would go with a), it's no harder to implement than c.
+>
+> Note that an efficient implementation of c) is not easy!
+> I can think of three approaches
+
+I think you would have to use both of the latter approaches; it's much the same
+as a case statement (where you need to use both table and sequence of if
+approaches). It shouldn't be possible to write something that would be
+inefficient for both approaches. I don't think the supposedly general approach
+is ever acceptable for static set predicates - it should be possible to iterate
+on small sets quickly, no matter what the base type is (including 128-bit
+integer).
+
+...
+> One final thought, it is odd to allow
+>
+> subtype R is Character with
+> predicate => R in 'A' | 'F' | 'W' .. 'Y';
+>
+> for J in R loop ...
+>
+> and to disallow
+>
+> for J in 'A' | 'F' | 'W' .. 'Y' loop ...
+
+We have to disallow this, it is ambiguous (Character, Wide_Character, etc.).
+It would be nice to be able to say:
+
+ for J in Character when 'A' | 'F' | 'W' .. 'Y' loop
+
+but of course there was a proposal like this which everyone agrees was an
+unnecessary idea. :-)
+
+> Obviously it is no harder to implement one than the other, so perhaps
+> we should give some thought to allowing the more general loop format?
+> when Z => I := Q;
+
+I suspect that doing this syntactically would be hard without running into
+ambiguities with the other new iterator forms. In addition, it would be a
+significant pain to give types to these things (as shown above), and they don't
+work without the types.
+
+It's interesting that you are rediscovering all of the features of the set
+constraint proposal, one by one, and finding them valuable. I just hope this
+doesn't result in a hodge-podge of rules rather than in integrated whole.
+
+****************************************************************
+
+From: Tucker Taft
+Date: Monday, October 4, 2010 4:30 PM
+
+> In this note, I want to specifically address the issue of looping
+> through predicated types with a syntax like
+>
+> for J in subtype loop
+>
+> It seems like we have three possibilities
+>
+> a) allow it always, the official semantics could be
+> b) forbid it entirely
+> c) allow it only for static predicates
+>
+> I can live with b, since I don't think it's terribly useful,...
+
+I vote for (b): disallow it entirely.
+It doesn't seem worth the trouble.
+There is the possibility of too much trickery happening behind the scenes. It
+reminds me of iterating over holey enumeration types, only worse.
+
+I also hope we are disallowing such subtypes for array index subtypes.
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Monday, October 4, 2010 4:17 PM
+
+> I suspect that some people are more friendly to the
+> (potentially-static) subtype predicate approach in that it piggy backs
+> on the aspect specification syntax. You are almost certainly right
+> that getting static predicates to work may require many of the same
+> things that the set constraints would have required, but avoiding
+> adding a new constraint syntax is a significant advantage for
+> predicates, at least to some people (including me, for what it is
+> worth), even if it ends up requiring more words in the RM.
+> Somehow additional syntax "weighs" a lot more than additional RM words
+> for most people.
+
+I sometimes think I'm drawing diagrams on a whiteboard in a room full of blind
+people. :-)
+
+I've said several times that the syntax itself doesn't bother me. What worries
+me is grafting on a boatload of special case rules to predicates and subtype
+declarations and case statements and for loops and gosh knows what else in order
+to support these things, and creating a maintenance headache in the meantime.
+You're the one who always is telling us that new features ought not look bolted
+on -- this seems like it has the potential to do that in the worst way possible.
+
+All I want is some (required) way to declare that you are defining one of these
+things. I suggested a separate aspect Set_Predicate which would allow case
+statements and loops and require the predicate expression to have a certain
+form, as well as trigger the needed semantic rules to make the case statements
+and loops work. That meets everything you say here, and I proposed it last week.
+
+I suspect part of the problem here is the mistaken emphasis on "static".
+That is not the important property here; the property that matter is a subtype
+that describes some set of values that aren't necessarily contiguous. Once this
+was described as "static", then a whole bunch of additional (and sometimes
+unnecessary) considerations arise. (For instance, Robert's suggested rules mean
+that you could not use a set predicate on a generic formal type, including on a
+formal integer type. That seems inconsistent and limiting to me. It seems
+perfectly possible to have set predicates on non-static subtypes - but don't
+worry Robert, I too am concerned about overgeneralization so I am not about to
+propose fully dynamic set predicates!)
+
+Anyway, since it is obvious that I'm not doing that well describing what I
+already know about this problem (and remember that Steve and I spent a lot of
+time last year in developing the set constraint proposal), and
+because it is becoming obvious that Robert is rediscovering the issues anyway,
+I'm going to try to hold my tongue on any further discussion here (I need to do
+work which will help progress the language).
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Monday, October 4, 2010 4:27 PM
+
+...
+> After all lost of things are not static that should be (my favorite
+> peeve in this area is that 'Size should always be static if you have
+> given an explicit static Size value in the program).
+
+Arggghhh!!! I complained about this problem last week and you said that "in
+15 years, no one has complained about this in the context of GNAT" (Friday,
+6:31 PM). (Any specified Size value has to be static by language rule, so this
+applies to essentially all uses of 'Size.) No wonder I feel like I am losing my
+mind...
+
+****************************************************************
+
+From: Robert Dewar
+Date: Monday, October 4, 2010 6:40 PM
+
+But you were using it in a very odd context, and my comment was about that odd
+context. But yes, I understand what you mean. Your example was trying to set the
+size of a record by summing the size of its components, but that seems plain odd
+and wrong, and really I was reacting to that :-)
+
+But I agree I was being inconsistent
+
+****************************************************************
+
+From: Robert Dewar
+Date: Monday, October 4, 2010 6:29 PM
+
+> Huh? For a static set predicate, the solution is to define the set of
+> values of the subtype. This also properly defines the set of values
+> for the case statement (and probably other cases that I can't remember
+> right now). That of course isn't possible for the general predicate case.
+
+Yes, you can do that if you like, and if it is not too much trouble, and that
+does make more sense if you intend to ban the non-static ase
+
+> But in order for that to work, there needs to be a clear distinction
+> between the two cases. I would prefer that distinction is one that
+> programmers are required to declare in some way (as it avoids
+> maintenance headaches caused by the semantics changing).
+
+I know you want that distinction, but so far I see *no one* else in favor of it. I certainly very much dislike making this distinction, and Bob Duff, who holds the pen also dislikes making this distinction.
+Unless there is some glimmer of support on this for your position, I don't consider it worth discussing further.
+
+> I think you would have to use both of the latter approaches; it's much
+> the same as a case statement (where you need to use both table and
+> sequence of if approaches). It shouldn't be possible to write
+> something that would be inefficient for both approaches. I don't think
+> the supposedly general approach is ever acceptable for static set
+> predicates - it should be possible to iterate on small sets quickly,
+> no matter what the base type is (including 128-bit integer).
+
+The case statement is the way to go on this, because it automatically takes
+advantage of the extensive optimization of case statements for various degrees
+of sparseness that is in all sophisticated code generators anyway.
+
+However, I am inclined to go with disallowing this completely now, given that
+you regard it as only viable if we make a clear syntactic distinction for static
+predicates, and Tuck doesn't like it anyway.
+
+I have implemented it, was fairly easy to do, but of course unimplementing it
+would be even quicker!
+
+>> for J in 'A' | 'F' | 'W' .. 'Y' loop ...
+>
+> We have to disallow this, it is ambiguous (Character, Wide_Character, etc.).
+
+Randy, don't you ever turn the excessive language lawyering off? :-=) Yes, of
+course this particular one is ambiguous (easily cured with qualification), but
+it is the general idea that needs to be addressed,
+
+Anyway, I think we should probably kill the entire loop business completely,
+then this becomes a dead issue as well.
+
+> I suspect that doing this syntactically would be hard without running
+> into ambiguities with the other new iterator forms. In addition, it
+> would be a significant pain to give types to these things (as shown
+> above), and they don't work without the types.
+
+I don't see particular pain here
+
+> It's interesting that you are rediscovering all of the features of the
+> set constraint proposal, one by one, and finding them valuable. I just
+> hope this doesn't result in a hodge-podge of rules rather than in integrated whole.
+
+I never said I found the loops valuable, I said I found them useless but
+harmless and that you liked them :-) :-)
+
+The critical capability of static predicates is to use them in case statements.
+I have that all working just fine.
+
+****************************************************************
+From: Steve Baird
+Date: Monday, October 4, 2010 4:33 PM
+
+> We
+> definitely don't want to be able to eliminate predicate changes in
+> cases where it is not allowed to eliminate range checks.
+>
+
+I completely agree. This is the idea that I was trying to capture.
+
+The question here concerns the rules regarding the elimination of range checks.
+However this question is resolved, I agree with your point that the rules for
+predicate check elimination should be consistent with those for range check
+elimination.
+
+So what about range checks?
+
+Given
+ type R is record F1, F2 : Natural; end record;
+
+ procedure P (X : in out R; Y : R) is
+ begin
+ X.F1 := Y.F1;
+ end P;
+
+are you arguing that a constraint check is required if it is possible that Y.F1
+might be uninitialized?
+
+13.9.1 says
+
+ If the representation of a scalar object does not represent a value of
+ the object's subtype (perhaps because the object was not initialized),
+ the object is said to have an invalid representation. It is a bounded
+ error to evaluate the value of such an object If the error is
+ detected, ...
+ Otherwise, execution continues using the invalid representation.
+ ...
+
+ The semantics of operations on invalid representations are as follows:
+
+ ...
+
+ If the representation of the object does not represent a value of
+ the object's type, the semantics of operations on such
+ representations is implementation-defined, but does not by itself
+ lead to erroneous or unpredictable execution, or to other objects
+ becoming abnormal
+
+As has been noted previously, an implementation always has the option of
+defining the representation -> value mapping for a given object to be such that
+no invalid representation ever represents a value of the object's type. So an
+implementation always has permission to go with implementation-defined behavior
+for an operation on such a value, subject only to the requirement that this must
+not "by itself" lead to war, death, pestilence, and famine. Nobody has ever come
+close to nailing down the meaning of "by itself", so the meaning of this
+requirement is unclear.
+
+Paragraph 13/3 certainly spells out one case in which scalar assignment with an
+invalid rhs is not required to raise an exception.
+
+I take all this to mean that an assignment statement whose rhs is the value of
+an invalid scalar object is not *required* to fail a range check.
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Monday, October 4, 2010 6:58 PM
+
+...
+> The question here concerns the rules regarding the elimination of
+> range checks. However this question is resolved, I agree with your
+> point that the rules for predicate check elimination should be
+> consistent with those for range check elimination.
+>
+> So what about range checks?
+>
+> Given
+> type R is record F1, F2 : Natural; end record;
+>
+> procedure P (X : in out R; Y : R) is
+> begin
+> X.F1 := Y.F1;
+> end P;
+>
+> are you arguing that a constraint check is required if it is possible
+> that Y.F1 might be uninitialized?
+
+Oh, please do not bring this up again. You asked essentially the same question
+last year, it was turned into AI05-0195-1, and this was discussed and voted No
+Action in Valencia: the language was felt to be clear enough.
+
+All I've said is that the rules are the same. The rules for a particular
+compiler depend on what it allows for invalid and valid values, and there is no
+requirement anywhere for those to be the same for different compilers, or even
+different switches in the same compiler (Janus/Ada has three different checking
+elimination models, depending on whether the user wants errors detected early or
+the fastest legal code).
+
+This is a case where compilers can move the "bump" all over the place.
+
+And this is all I'm going to say on this topic.
+
+P.S. Whatever gave you the idea that I had any intention whatsoever in meddling
+in this can of worms??
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Monday, October 4, 2010 7:35 PM
+
+...
+> > But in order for that to work, there needs to be a clear distinction
+> > between the two cases. I would prefer that distinction is one that
+> > programmers are required to declare in some way (as it avoids
+> > maintenance headaches caused by the semantics changing).
+>
+> I know you want that distinction, but so far I see *no one* else in
+> favor of it. I certainly very much dislike making this distinction,
+> and Bob Duff, who holds the pen also dislikes making this distinction.
+> Unless there is some glimmer of support on this for your position, I
+> don't consider it worth discussing further.
+
+Obviously I'd like to see some support for this position, but so far I've seen
+hardly any support for *your* position, either. Indeed, hardly anyone has
+participated in this discussion, so I wouldn't draw any conclusions from it.
+
+In any case, I will never be able to support mixing these two distinct things in
+a way which will prevent improving either of them in the future. And I will do
+everything I can to stop such an addition to the language.
+
+...
+> >> for J in 'A' | 'F' | 'W' .. 'Y' loop ...
+> >
+> > We have to disallow this, it is ambiguous (Character,
+> Wide_Character, etc.).
+>
+> Randy, don't you ever turn the excessive language lawyering off? :-=)
+> Yes, of course this particular one is ambiguous (easily cured with
+> qualification), but it is the general idea that needs to be addressed,
+
+My entire point was that you need a way to get the type name into such things.
+Qualification is a really ugly way to do it and also unfamilar (I don't think
+I've ever used qualification other than to debug expressions that were
+mysteriously not resolving, and I don't think I've ever left the qualifications
+around after fixing the error - I always name the type).
+
+...
+> > It's interesting that you are rediscovering all of the features of
+> > the set constraint proposal, one by one, and finding them valuable.
+> > I just hope this doesn't result in a hodge-podge of rules rather
+> > than in integrated whole.
+>
+> I never said I found the loops valuable, I said I found them useless
+> but harmless and that you liked them :-) :-)
+
+The loops was not what I was referring to...I was referring to your "pragma
+Static" (which appears to be providing some of the distinction that I was
+discussing before), to the idea that you might want to declare an anonymous set
+predicate, etc.
+
+> The critical capability of static predicates is to use them in case
+> statements. I have that all working just fine.
+
+I find case statements and for loops to be closely related. But apparently,
+anything I think on this topic is way out in left field. I have to wonder why I
+bother at all...(Note: I rarely charge e-mail discussions to my ARG work; all of
+these have been on my own time.)
+
+****************************************************************
+
+From: Robert Dewar
+Date: Monday, October 4, 2010 8:09 PM
+
+> In any case, I will never be able to support mixing these two distinct
+> things in a way which will prevent improving either of them in the future.
+> And I will do everything I can to stop such an addition to the language.
+
+Hmmm, reminds me of JDI, who would furiously hold on to his position even when
+it was N-1 against :-). I always figure that if I can't convince others, then I
+am either wrong, or presenting the argument incompetently.
+
+Of course it is true that others need to weigh in on this, I know Bob Duff is
+very opposed to distinguishing the two, and I know I am, and I know you are very
+interested in having this distinction.
+
+To me they are not distinct at all, no more distinct than the normal case of
+
+ X : constant Integer := expression;
+
+where X can be used in very different contexts (including the case we are
+discussing here, case statements), depending on the nature of expression. I
+don't find this case any different (you may find them the same too, in one
+message you claimed this was a mistake in the language in this case as well),
+but to me if something is in Ada for two decades and we live with it, claiming
+it is a big mistake is kind of besides the point.
+
+So anyway, how about it other-arg-folks .. cast your vote :-) Do you want to see
+two separate aspects here one for general predicates one for what Randy likes to
+call set predicates, and I like to call static predicates, or one single aspect
+as now, with a recognition of static forms corresponding to a very set and
+simple syntax (set membership with static right sides).
+
+Looks like it is lining up that the ONLY distinction is whether they can be used
+in case statements, since I think we are likely to lose the loops given cool
+support for looping over these beasts. And no Tuck, no one is suggesting them as
+array indexes :-)
+
+> My entire point was that you need a way to get the type name into such
+> things. Qualification is a really ugly way to do it and also unfamilar
+> (I don't think I've ever used qualification other than to debug
+> expressions that were mysteriously not resolving, and I don't think
+> I've ever left the qualifications around after fixing the error - I always name the type).
+
+I use qualification ALL the time to disambiguate, that's what it's there for, I
+find it amazing you haven't -- another way in which I think the RB Ada coding
+style is a bit different from most of the world. Of course aren't you one of
+these anti-use fanatics. If you are in that camp, then of course you need to
+disambiguate less.
+
+>> I never said I found the loops valuable, I said I found them useless
+>> but harmless and that you liked them :-) :-)
+>
+> The loops was not what I was referring to...I was referring to your
+> "pragma Static" (which appears to be providing some of the distinction
+> that I was discussing before), to the idea that you might want to
+> declare an anonymous set predicate, etc.
+
+These are just passing ideas, the pragma Static is just a passing idea, often it
+is appropriate to do with pragmas that which you do NOT want to burden the
+language with, and I think this is a good example. But in any case, I would
+prefer to keep things simple in the actual proposal and limit it to case
+statements, which is really the critical need.
+
+>> The critical capability of static predicates is to use them in case
+>> statements. I have that all working just fine.
+>
+> I fine case statements and for loops to be closely related. But
+> apparently, anything I think on this topic is way out in left field. I
+> have to wonder why I bother at all...(Note: I rarely charge e-mail
+> discussions to my ARG work; all of these have been on my own time.)
+
+Case statements and for loops *are* closely related from a language lawyer point
+of view, I agree, but in usage, there is a world of difference. I have never
+ever needed to iterate through an enumeration subtype! I use case statements on
+enumeration subtypes all the time. So it is for me a differentiation of usage.
+
+For entertainment, here is a test program (as I told you I did implement
+iteration over predicated types :-)
+
+> 1. with Text_IO; use Text_IO;
+> 2. procedure Predicate_Loops is
+> 3. type Int is range 1 .. 10;
+> 4.
+> 5. procedure Q (X : Int) is
+> 6. subtype NonStaticP is Int with
+> 7. predicate => NonStaticP > X;
+> 8. begin
+> 9. for J in NonStaticP loop
+> 10. Put_Line ("non static:" & J'Img);
+> 11. end loop;
+> 12. end;
+> 13.
+> 14. subtype StaticP is Int with
+> 15. predicate => StaticP in 3 | 5 .. 7 | 10;
+> 16.
+> 17. begin
+> 18. for J in StaticP loop
+> 19. Put_Line ("static:" & J'Img);
+> 20. end loop;
+> 21.
+> 22. Q (5);
+> 23. end;
+
+And the output is:
+
+> static: 3
+> static: 5
+> static: 6
+> static: 7
+> static: 10
+> non static: 6
+> non static: 7
+> non static: 8
+> non static: 9
+> non static: 10
+
+The expanded code for the non-static case loop looks like:
+
+> -- 9: for J in NonStaticP loop
+> L_1 : for j in 1 .. 10 loop
+> if predicate_loops__q__nonstaticpPredicate (j) then
+>
+> -- 10: Put_Line ("non static:" & J'Img);
+ >
+> ... lots of concatenation and IO crud
+>
+> -- 11: end loop;
+> end L_1__B3b;
+> end if;
+> end loop L_1;
+
+This is the code that can take a long time, if you concoct an example that is
+very sparse over a giant type :-)
+
+The expanded code for the static case loop looks like:
+
+> -- 18: for J in StaticP loop
+
+> B29b : declare
+> j : predicate_loops__staticp := 3;
+>
+> begin
+> loop
+
+> -- 19: Put_Line ("static:" & J'Img);
+
+> ... lots of concatenation and IO crud
+>
+
+> -- 20: end loop;
+
+> case j is
+> when 3 =>
+> j := 5;
+> when 7 =>
+> j := 10;
+> when 10 =>
+> exit;
+> when others =>
+> j := predicate_loops__staticp'succ(j);
+> end case;
+> end loop;
+> end B29b;
+
+This approach with the case statement guarantees nice linear performance with
+minimal overhead, The compiler does a good job of figuring out how to optimize
+case statements, and this particular one will likely come out as a jump table,
+but might be if's depending on the details of the target architecture.
+
+I think looking at this, I do agree with Tuck, the non-static case is too much
+hidden overhead, and after all you can always do this yourself if you want.
+
+On the other hand, the static case, you definitely can't do yourself, not
+without knowing exactly what literals are present, and the whole point is to
+avoid this.
+
+BTW, in GNAT we have the (optional) concept of unordered enumeration types. If
+you select this option, then all enumeration types are considered unordered
+unless you apply a pragma Ordered to them. Then for unordered enum types, you
+get warnings on stuff like comparisons or First/Last.
+
+I think I probably will arrange for gnat to always consider these predicated
+enumeration types to be unordered, that really seems to make sense to me (it's
+just a matter of what warnings are generated by default, nothing to do with
+legality).
+
+-- The following is off-topic, read only
+-- if you have nothing better to do!
+
+P.P.S I mused the other day about reintroducing under the GNAT extensions
+switch, the old Ada 79 notion of unordered enums
+
+ type X is (A | B | C | D | E | F);
+
+then of course the subtypes could be written
+
+ subtype Y is X with
+ predicate Y in (B | D | F);
+
+(I *keep* wanting to put parens around the the set :-))
+
+and if you are in a really naughty mood you could allow
+
+ type X is {A | B | C | D | E | F};
+
+ subtype Y is X with
+ predicate Y in {B | D | F};
+
+since W is not around to complain about his keypunch.
+
+Note that this would be VERY easy to implement in GNAT, since as I say, at the
+level of warning messages we already have the full mechanism for unordered enum
+types :-)
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Monday, October 4, 2010 11:37 PM
+
+...
+> > My entire point was that you need a way to get the type name into
+> > such things. Qualification is a really ugly way to do it and also
+> > unfamiliar (I don't think I've ever used qualification other than to
+> > debug expressions that were mysteriously not resolving, and I don't
+> > think I've ever left the qualifications around after fixing the
+> > error - I always name the type).
+>
+> I use qualification ALL the time to disambiguate, that's what it's
+> there for, I find it amazing you haven't -- another way in which I
+> think the RB Ada coding style is a bit different from most of the
+> world. Of course aren't you one of these anti-use fanatics. If you are
+> in that camp, then of course you need to disambiguate less.
+
+I don't quite think I'm a "fanatic" on "use clauses"; I just limit their use to
+very common packages. I do use "use type" frequently, and probably will use "use
+all type" as well. I'll probably use the package use even less as "use all type"
+is more limited and covers the main reason that I use "use" at all: enumeration
+literals. (Full qualification on the instruction names in the Janus/Ada
+intermediate code would cause one's head to explode. :-) Anyway, you are
+probably right, this is a contributing factor in my not using qualification that
+often.
+
+...
+> Case statements and for loops *are* closely related from a language
+> lawyer point of view, I agree, but in usage, there is a world of
+> difference. I have never ever needed to iterate through an enumeration
+> subtype! I use case statements on enumeration subtypes all the time.
+> So it is for me a differentiation of usage.
+
+I find that odd; I've definitely iterated through enumeration subtypes (and not
+just for testing). For instance, I often have arrays indexed by an enumeration
+and it is not usual that some operation on that array or part of it needs
+iteration. It's not something that comes up everyday, but it's not that rare,
+either. I only used testing for an example because it was the simplest case I
+could think of that didn't involve arrays (as those won't work for sets).
+
+...
+> I think looking at this, I do agree with Tuck, the non-static case is
+> too much hidden overhead, and after all you can always do this
+> yourself if you want.
+
+I agree completely.
+
+> On the other hand, the static case, you definitely can't do yourself,
+> not without knowing exactly what literals are present, and the whole
+> point is to avoid this.
+
+Right. I probably would have implemented this with a table of items (if the
+number of items is small), or something like you have otherwise (the case table
+jump table and set up code would be at lot larger than the item table for
+typical enumeration types - which usually get 8-bit representations in our
+compiler).
+
+...
+> -- The following is off-topic, read only
+> -- if you have nothing better to do!
+
+That is always intriguing. ;-)
+
+> P.P.S I mused the other day about reintroducing under the GNAT
+> extensions switch, the old Ada 79 notion of unordered enums
+>
+> type X is (A | B | C | D | E | F);
+>
+> then of course the subtypes could be written
+>
+> subtype Y is X with
+> predicate Y in (B | D | F);
+>
+> (I *keep* wanting to put parens around the the set :-))
+
+I thought that the syntax of memberships required it. Or did we change our minds
+on that one? I forget. (I would much rather that it did have the parens, as that
+would make it clear that
+ Y in (1 .. 10)
+is a set membership. Depending on what resolution rules we end up with, that
+could be helpful.)
+
+> and if you are in a really naughty mood you could allow
+>
+> type X is {A | B | C | D | E | F};
+>
+> subtype Y is X with
+> predicate Y in {B | D | F};
+>
+> since W is not around to complain about his keypunch.
+
+I actually semi-seriously had suggested something like this for set constraints.
+But it got even less traction than the constraints themselves. :-(
+
+****************************************************************
+
+From: Gary Dismukes
+Date: Tuesday, October 5, 2010 1:16 AM
+
+> So anyway, how about it other-arg-folks .. cast your vote :-) Do you
+> want to see two separate aspects here one for general predicates one
+> for what Randy likes to call set predicates, and I like to call static
+> predicates, or one single aspect as now, with a recognition of static
+> forms corresponding to a very set and simple syntax (set membership
+> with static right sides).
+
+I think they should be part of one predicate aspect. I can't see splitting them
+into two separate aspects, to me that would seem confusing and just complicate
+things unnecessarily, plus being inconsistent with how staticness is normally
+handled.
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Tuesday, October 5, 2010 1:49 AM
+
+Sigh. As I've repeatedly said, this has nothing to do with staticness (its about
+sets). Simply by calling it that, Robert has managed to get everyone confused.
+
+Robert said earlier:
+
+>I always figure that if I can't convince others, then I am either
+>wrong, or presenting the argument incompetently.
+
+Unfortunately, with me, it seems that unless the issue is clear cut, I am
+*always* doing that latter. I can't always be wrong...(and if I am, I should be
+replaced).
+
+****************************************************************
+
+From: Robert Dewar
+Date: Tuesday, October 5, 2010 3:58 AM
+
+> Sigh. As I've repeatedly said, this has nothing to do with staticness
+> (its about sets). Simply by calling it that, Robert has managed to get
+> everyone confused.
+
+Couldn't disagree more
+
+sets have nothing to do with staticness
+
+staticness has everything to do with being able to use things in case statements
+
+a predicate defines a subset of an enumeration type (or other discrete type).
+
+the issue is whether this set of values is statically known at compile time.
+
+if so, then it can be used in a case statement
+
+this is *EXACTLY* the same general concept that underlies the issue of normal
+static constants
+
+ X : constant Integer := expression;
+
+you can use X in some remote case statement if and only if expression is known
+at compile time. Known at compile time is to amorphous a predicate, so we
+introduce a clearly defined syntax rule that defines that certain expressions
+must be known at compile time.
+
+ subtype x is enum with
+ predicate => expression;
+
+(cut and paste!)
+you can use X in some remote case statement if and only if expression is known
+at compile time. Known at compile time is to amorphous a predicate, so we
+introduce a clearly defined syntax rule that defines that certain expressions
+must be known at compile time.
+
+The analogy is to me 100% appropriate, hence the reuse of the term static.
+
+On the other hand, "set" has no implication of staticness to me, so does not
+capture this distinction. the subtype declaration above ALWAYS defines a subset
+of enum, whether or not it is static. So the issue is not sets per se, it is
+statically known subsets.
+
+I think it is Randy who creates the confusion by insisting on the term "set" to
+describe static sets.
+
+you can use X in some remote
+
+****************************************************************
+
+From: Robert Dewar
+Date: Tuesday, October 5, 2010 4:11 AM
+
+> Right. I probably would have implemented this with a table of items
+> (if the number of items is small), or something like you have
+> otherwise (the case table jump table and set up code would be at lot
+> larger than the item table for typical enumeration types - which
+> usually get 8-bit representations in our compiler).
+
+Well for such a marginal feature, it is hardly worth having yet another special
+way of doing things when the case statement always provides reasonable linear
+performance. Sure it's a bit better in some cases, but there are MANY other
+cases more worthwhile for improving performance. But you can't use the table of
+items in all cases
+
+ subtype R is Integer with
+ predicate R in -Integer'First .. -1 | +1 .. Integer'Last;
+
+can't be done with a table :-)
+
+>> P.P.S I mused the other day about reintroducing under the GNAT
+>> extensions switch, the old Ada 79 notion of unordered enums
+>>
+>> type X is (A | B | C | D | E | F);
+>>
+>> then of course the subtypes could be written
+>>
+>> subtype Y is X with
+>> predicate Y in (B | D | F);
+>>
+>> (I *keep* wanting to put parens around the the set :-))
+>
+> I thought that the syntax of memberships required it. Or did we change
+> our minds on that one? I forget. (I would much rather that it did have
+> the parens, as that would make it clear that
+> Y in (1 .. 10)
+> is a set membership. Depending on what resolution rules we end up
+> with, that could be helpful.)
+
+We do not require parens here (because we don't in other contexts such as case.
+
+>> and if you are in a really naughty mood you could allow
+>>
+>> type X is {A | B | C | D | E | F};
+>>
+>> subtype Y is X with
+>> predicate Y in {B | D | F};
+>>
+>> since W is not around to complain about his keypunch.
+>
+> I actually semi-seriously had suggested something like this for set
+> constraints. But it got even less traction than the constraints themselves.
+> :-(
+
+Right, this is not a tractiony proposal :-)
+
+****************************************************************
+
+From: Tucker Taft
+Date: Tuesday, October 5, 2010 11:49 AM
+
+>> I'm curious why you don't think it
+>> is reasonable to generalize to all equality/ relational operators. X
+>> in 1..10 is essentially equivalent to X>= 1 and X<= 10, so it seems
+>> odd to specifically require membership.
+>> And as you pointed out, "X /= 0" is certainly more readable and
+>> natural than X in blah'first .. -1 |
+>> +1 .. blah'last. There are already restrictions
+>> in the use of discriminants that they must be used alone rather than
+>> as part of a larger expression, so this feels somewhat in the same
+>> ballpark.
+>
+> I just think that fully analyzing expressions like
+>
+> (X >= 1 and <= 10) or ... and ..
+>
+> will be a bit of an implementation nightmare ...
+
+I don't agree with this. I believe that if we restrict it to just the form of a
+single membership, we are falling into the trap of defining it syntactically,
+which is to some extent what Randy has been objecting to.
+
+If we are using the notion of a "static" predicate I believe we should define it
+semantically, with some attention to implementability, including representing
+the static predicate in the symbol table in finite space. One implementability
+criteria might be that a static (discrete) predicate should be representable as
+a list of ranges, where the number of ranges in the list is proportional to the
+size of the predicate expression.
+
+Clearly you can represent "X >= 1" as a single range (1..Int'Last), and "X <=
+10" as a single range. "And" means "intersection" and "or" means union the
+ranges.
+
+There are actually very few operators which cause the number of ranges to be
+disproportional to the size of the predicate. "mod"/"rem" in particular are
+nasty ones, as are some of the bit-wise and/or/xor operators. For example,
+"mod" is bad because "X mod 10 = 0" produces 2*int'last/10 ranges, roughly.
+
+Not many other operators pose much of a challenge as far as computing the
+ranges. I would disallow the operators that break the proportionality rule, and
+allow all the others.
+
+****************************************************************
+
+From: Tucker Taft
+Date: Tuesday, October 5, 2010 1:34 PM
+
+FWIW, in our compiler, we already have a list-of-ranges representation we use
+when checking case statements for gaps or overlaps, so perhaps in some
+implementations this same list-of-ranges representation could be used to
+represent static predicates. You would need to implement the "and" operation
+(intersection). Presumably you already have an "or" operation that operates on
+list-of-ranges since that is what happens each time you see another choice list
+in the case statement.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Tuesday, October 5, 2010 4:54 PM
+
+Well I just implemented the set membership form for now, I am dubious about
+adding more bells and whistles!
+
+****************************************************************
+
+From: Steve Baird
+Date: Tuesday, October 5, 2010 12:53 PM
+
+> So anyway, how about it other-arg-folks .. cast your vote :-) Do you
+> want to see two separate aspects here one for general predicates one
+> for what Randy likes to call set predicates, and I like to call static
+> predicates, or one single aspect as now, with a recognition of static
+> forms corresponding to a very set and simple syntax (set membership
+> with static right sides).
+
+I agree with Robert.
+
+I'd like to see rules pertaining to garden-variety subtype predicates along the lines (at least in effect) of
+ "and if the predicate happens to satisfy the following
+ additional conditions, then they can be used in
+ the following additional ways".
+
+Randy, reasonably enough, might respond - "of course that would be nice, but the
+devil is in the details - we need a specific proposal".
+
+I'll happily leave that to Bob.
+
+Incidentally, I assume that the rules for case statements and variant parts
+would remain consistent - I hope we are not talking about allowing these
+subtypes in one of these contexts and not the other.
+
+****************************************************************
+
+From: John Barnes
+Date: Wednesday, October 6, 2010 1:55 AM
+
+I have not followed this in intimate detail becuase I have been too busy writing
+the Rationale for the bits that are settled (and that I do understand).
+
+However, I am in favour of just one feature with perhaps special features in
+some circumstances.Much easier to explaiin than having two quite separate things
+which seem to overlap. Could be very confusing for most users.
+
+Back to the Rat.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Wednesday, October 6, 2010 2:11 AM
+
+> Incidentally, I assume that the rules for case statements and variant
+> parts would remain consistent - I hope we are not talking about
+> allowing these subtypes in one of these contexts and not the other.
+
+Yes, of course, and also for choices in aggregates. In the GNAT implementation,
+these are handled by a single common generic, so the changes for predicates
+affect all three in an identical manner.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Wednesday, October 6, 2010 2:20 AM
+
+> Not many other operators pose much of a challenge as far as computing
+> the ranges. I would disallow the operators that break the
+> proportionality rule, and allow all the others.
+
+Seems like over-complexification to me, compared to a simple syntactic rule. I
+find the current set of rules on what is and what is not static for expressions
+to be a nasty mess. I hate to replicate the same kind of thing here, and it will
+definitely add a considerable burden to the implementation. Is it really worth
+it, given that 9x% of the use of static predicates will be for non-contiguous
+enumeration subtypes for which the set notation is perfectly adequate.
+
+Why do we always have to take simple things and make them over-complex in an
+attempt to over-generalize in ways that are not really useful.
+
+That being said, I think a critical part of the argument above is the 9x% guess.
+If it is really the case that the predicate feature will be used extensively for
+things like non-zero integer, I certainly agree that
+
+ subtype Non_Zero_Integer is Integer with
+ Predicate =>
+ Non_Zero_Integer /= 0;
+
+is clearer and neater than
+
+ subtype Non_Zero_Integer is Integer with
+ Predicate =>
+ Non_Zero_Integer in
+ Integer'First .. -1 | +1 .. Integer'Last;
+
+The question is .. how often will this sort of thing occur in practice. I am
+guessing very rarely (I have never for example felt any need for this particular
+non-zero-integer subtype in an actual program -- it is of course a neat concept
+-- but to me it is just that a neat concept, not a useful feature).
+
+And if you do generalize, it seems you still have arbitrary restrictions, if you
+for instance exclude mod 2 on the basis of implementation difficulties.
+
+I am *NOT* suggesting we allow
+
+ subtype Even_Integer is Integer with
+ Predicate => Even_Integer mod 2 = 0;
+
+to be considered static
+
+since indeed it would be a nightmare to implement.
+But if your notion of a static predicate is a subset known at compile time, it
+seems arbitrary to say that this particular (obviously known at compile time)
+subset is not static.
+
+Given we end up with arbitrary rules anyway, I think that having a very simple
+syntactic rule makes things easier for the programmer without significantly
+restricting expressive power.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Wednesday, October 6, 2010 2:28 AM
+
+> FWIW, in our compiler, we already have a list-of-ranges representation
+> we use when checking case statements for gaps or overlaps, so perhaps
+> in some implementations this same list-of-ranges representation could
+> be used to represent static predicates. You would need to implement
+> the "and" operation (intersection).
+> Presumably you already have an "or" operation that operates on
+> list-of-ranges since that is what happens each time you see another
+> choice list in the case statement.
+
+We have a list of ranges too, but we don't have even a general OR operation, we
+just keep the list of ranges sorted, and that's good enough to check for
+overlaps and gaps.
+
+So we would have to implement both a general AND and a general OR on lists of
+ranges, plus all the mechanism for multiple lists of ranges. Could be done, but
+would be a significant implementation effort, probably considerably more work
+than has been done for static predicates in their current restricted form.
+
+Is this extra work worthwhile? I am dubious!
+
+BTW, the initial GNAT implementation for static predicates (that will be in our
+Ada 2012 preview release) so far looks like this:
+
+A predicate is static if it has the syntactic form of a set membership with all
+static alternatives (obviously we could add to this later if the consensus is to
+generalize).
+
+Static predicates can be used in case statements, variant parts, case
+expressions and aggregates in the obvious way.
+
+You can loop through a static predicated type (but NOT through a non-static
+predicated type). We could forbid this (or more likely put it under control of
+the -gnatX extension switch) later if we decide to forbid it, but thinking
+things through, I think it does make sense to go this far (but not allow these
+things as array indexes).
+
+****************************************************************
+
+From: Tucker Taft
+Date: Wednesday, October 6, 2010 2:38 AM
+
+> The question is .. how often will this sort of thing occur in
+> practice. I am guessing very rarely (I have never for example felt any
+> need for this particular non-zero-integer subtype in an actual program
+> -- it is of course a neat concept -- but to me it is just that a neat
+> concept, not a useful feature).
+
+It is pretty common in my experience to have a type with a value that means
+"undefined" and it would seem pretty typical to have a predicate that
+represented "not undefined." In the same way we have "not null."
+
+Similarly, there might be a couple of values not handled by a given routine, and
+it is most natural to write:
+
+ subtype Simple_Expr_Kind is Expr_Kind
+ with Predicate =>
+ Simple_Expr_Kind /= Membership_Kind
+ and then
+ Simple_Expr_Kind /= Relational_Kind;
+
+Having to convert this to three ranges would be a pain, and a maintenance burden
+if additional Expr_Kinds are added.
+
+I agree we probably end up with something that seems a bit arbitrary, but I find
+only allowing membership is a bit *too* arbitrary for my taste. Including
+relational and equality operators (and "not in"), joined by logical operators,
+seems very straightforward to implement. Perhaps going beyond that is overkill.
+
+****************************************************************
+
+From: Tucker Taft
+Date: Wednesday, October 6, 2010 2:39 AM
+
+> BTW, the initial GNAT implementation for static predicates (that will
+> be in our Ada 2012 preview release) so far looks like this:
+>
+> A predicate is static if it has the syntactic form of a set membership
+> with all static alternatives (obviously we could add to this later if
+> the consensus is to generalize). ...
+
+Do you allow "not in"?
+
+****************************************************************
+
+From: Robert Dewar
+Date: Wednesday, October 6, 2010 3:01 AM
+
+> Similarly, there might be a couple of values not handled by a given
+> routine, and it is most natural to write:
+>
+> subtype Simple_Expr_Kind is Expr_Kind
+> with Predicate =>
+> Simple_Expr_Kind /= Membership_Kind
+> and then
+> Simple_Expr_Kind /= Relational_Kind;
+
+Well that would be a bit strange, since the natural way to write this would be
+
+ with Predicate =>
+ Simple_Expr_Kind not in
+ Membership_Kind | Relational_Kind;
+
+:-) [I know, takes getting used to new features] and of course NOT IN would not
+be static either.
+
+> Having to convert this to three ranges would be a pain, and a
+> maintenance burden if additional Expr_Kinds are added.
+
+That's a strong argument
+
+> I agree we probably end up with something that seems a bit arbitrary,
+> but I find only allowing membership is a bit *too* arbitrary for my
+> taste. Including relational and equality operators (and "not in"),
+> joined by logical operators, seems very straightforward to implement.
+> Perhaps going beyond that is overkill.
+
+"very straightforward to implement"
+
+Sure, no conceptual problems, but a LOT of rather tricky code with lots of
+special cases to do it efficiently (if we could use bit vectors that would be
+easier, but not too appetizing for subtypes of 64-bit integer :-))
+
+I am tending in the direction of agreeing that we need this generalization.
+
+I really think we could allow ONLY
+AND and OR (and not XOR)
+
+the short circuit forms I would disallow, they make no sense in a static
+definition of a subset!
+
+****************************************************************
+
+From: Robert Dewar
+Date: Wednesday, October 6, 2010 3:08 AM
+
+> Do you allow "not in"?
+
+No, not currently, but anything is possible, I agree that NOT IN at least is a
+strong argument, having to figure out positive ranges is unacceptable.
+
+Once you allow NOT IN, you have a fairly big generalization anyway, and you
+really want to allow something like
+
+ subtype Special_Euro_Zone is European_Countries
+ with Predicate =>
+ Special_Euro_Zone in Euro_Zone
+ and
+ Special_Euro_Zone /= Greece;
+
+If you allow general use of OR and AND, then there is no reason to forbid
+inheritance from subtypes that themselves have static predicates, allowing the
+above to be written
+
+ subtype Special_Euro_Zone is Euro_Zone
+ with Predicate =>
+ Special_Euro_Zone /= Greece;
+
+I am convinced by Tuck's arguments, I think we have to generalize.
+
+a) allow inheriting from static predicates
+
+b) allow static equality and comparisons (yes, Randy, they aren't really static, since they have an occurrence of the type, but I think everyone knows what we mean here)
+
+c) allow set membership in static list (IN and NOT IN)
+
+d) allow AND/OR
+
+Is that enough?
+It's already a huge amount of work, I doubt we will get this into the 2012
+preview, but that does not matter.
+
+****************************************************************
+
+From: Edmond Schonberg
+Date: Wednesday, October 6, 2010 9:59 AM
+
+...
+> I agree we probably end up with something that seems a bit arbitrary,
+> but I find only allowing membership is a bit *too* arbitrary for my
+> taste. Including relational and equality operators (and "not in"),
+> joined by logical operators, seems very straightforward to implement.
+> Perhaps going beyond that is overkill.
+
+To my mind, membership is not arbitrary at all, it's exactly what is needed. In
+way, leaving aside the fact that we are speaking about finite sets only, this is
+like the distinction between recursive sets and recursively enumerable sets. In
+one case you have an effective procedure to generate the elements of the set, in
+the other you have a predicate that you have to apply to a (much larger) domain
+to determine whether an element of that domain belongs in the set. If the set
+is recursive, iterating over it is a natural thing to do. So my choice would be
+to say that a predicate is static if it is given by an extended membership
+expression (no negation allowed). This gives you case statements and loops
+without semantic complications, and the description in the RM is one sentence.
+
+****************************************************************
+
+From: Tucker Taft
+Date: Wednesday, October 6, 2010 10:37 AM
+
+> ... So my choice would be to say that a predicate is static if it is
+> given by an extended membership expression (no negation allowed).
+> This gives you case statements and loops without semantic
+> complications, and the description in the RM is one sentence.
+
+Including "not in" seems very straightforward, and eliminates a maintenance
+headache involved with specifying the multiple ranges necessary to leave exactly
+the right gaps. "not in" would at least address the most basic case of "X /=
+Blah_Kind and X /= Blur_Kind", via "X not in Blah_Kind | Blur_Kind".
+
+****************************************************************
+
+From: Edmond Schonberg
+Date: Wednesday, October 6, 2010 10:42 AM
+
+I guess the compiler could easily transform this into a sequence of ranges. As
+long as it is a single membership test (possibly negated) with no other
+operators in sight it would be OK to declare this static. The description is a
+few tokens longer....
+
+****************************************************************
+
+From: Robert Dewar
+Date: Wednesday, October 6, 2010 5:13 PM
+
+> To my mind, membership is not arbitrary at all, it's exactly what is
+> needed. In way, leaving aside the fact that we are speaking about
+> finite sets only, this is like the distinction between recursive sets
+> and recursively enumerable sets. In one case you have an effective
+> procedure to generate the elements of the set, in the other you have a
+> predicate that you have to apply to a (much larger) domain to
+> determine whether an element of that domain belongs in the set. If
+> the set is recursive, iterating over it is a natural thing to do. So
+> my choice would be to say that a predicate is static if it is given by
+> an extended membership expression (no negation allowed). This gives
+> you case statements and loops without semantic complications, and the
+> description in the RM is one sent
+
+As you know, this is what I was arguing earlier, but I have changed my mind
+after reading Tuck's example. The most potent of these is this kind of thing:
+
+ type European_Country is (England, Andorra, .....)
+
+ subtype Signifiant_European_Country is
+ European_Country with
+ Predicate
+ European_Countrg not in Andorra | Lichtenstein;
+
+Requiring you to do this with a positive set membership is a bit painful.
+
+Either you list all the entries, or you work out the three ranges depending on
+the order, neither is nearly as clearly self-documenting, and either of these
+work arounds is a maintenance headache, because you need to modify the subtype
+if you add a new significant european country.
+
+I really think the more general form is desirable, and it is not that hard to
+implement (I am currently implementing a full form including
+
+o inheritance of static predicates (and'ed with new
+ predicate)
+
+o primaries are IN NOT-IN equality and comparisons
+
+o Allowed connectors are NOT AND OR AND-THEN OR-ELSE XOR
+
+Really not that hard to do and much more general
+ Defined_Country is Country with
+ Defined_Country /= No_Country;
+
+****************************************************************
+
+From: Robert Dewar
+Date: Wednesday, October 6, 2010 5:14 PM
+
+> Including "not in" seems very straightforward, and eliminates a
+> maintenance headache involved with specifying the multiple ranges
+> necessary to leave exactly the right gaps. "not in"
+> would at least address the most basic case of "X /= Blah_Kind and X /=
+> Blur_Kind", via "X not in Blah_Kind | Blur_Kind".
+
+For me once you have NOT IN, you might as well generalize further, I definitely
+agree that NOT IN should be included.
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Date: Thursday, October 7, 2010 3:56 AM
+
+> Hmmm, reminds me of JDI, who would furiously hold on to his position
+> even when it was N-1 against :-).
+
+Yes - but he was right (keeping derived types, IIRC)!
+
+> So anyway, how about it other-arg-folks .. cast your vote :-)
+
+I didn't speak up because I'm uncertain...
+On one hand, having things like case statements allowed only for static cases is
+familiar. OTOH, having a different notion of staticness just for this case seems
+strange (and hard to teach, which is a concern for me).
+
+If the issue is with huge sets, wouldn't it be a pity to restrict the feature
+for reasonably sized sets? Allow general syntax for types with less than an
+implementation-defined limit (required by the standard to be at least 256,
+f.e.)?
+
+> Do you want to see two separate aspects here one for general
+> predicates one for what Randy likes to call set predicates, and I like
+> to call static predicates, or one single aspect as now, with a
+> recognition of static forms corresponding to a very set and simple
+> syntax (set membership with static right sides).
+
+If static really means static, I prefer one aspect. If there is a totally
+different definition of "static", I'm not so sure.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Thursday, October 7, 2010 5:48 AM
+
+> If the issue is with huge sets, wouldn't it be a pity to restrict the
+> feature for reasonably sized sets? Allow general syntax for types with
+> less than an implementation-defined limit (required by the standard to
+> be at least 256, f.e.)?
+
+I don't think that's a good approach. The mod stuff is really a bit of a red
+herring, I don't think it will come up in practice, but the excluded bad value
+case is definitely common.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Thursday, October 7, 2010 6:33 AM
+
+> If static really means static, I prefer one aspect. If there is a
+> totally different definition of "static", I'm not so sure.
+
+Well even if you try to generalize further you need special rules.
+As Randy has pointed out the expression here will never be a static expression
+exactly in the 4.9 sense, since it contains references to the type, e.g.
+
+ subtype X is Integer with
+ predicate X /= 0;
+
+Obviously X /= 0 is not a static expression, since what the heck is X in 4.9
+terms, so special rules are needed in any case (and of course these special
+rules are needed whether or not you use a separate aspect name for static
+predicates).
+
+Again my set of rules that I proposed is
+
+The expression consists of
+
+ a) set membership (IN or NOT IN), where the left side is
+ an instance of the subtype name, and the right side is
+ a list of static expressions or static subtype names.
+
+ b) comparison op with one side being an instance of the subtype
+ name, and the other side is a static expression.
+
+ c) static expressions (True is at least useful!)
+
+ d) recursively expressions allowed by these rules connected
+ by AND or OR or NOT.
+
+
+Additionally
+
+ a) the range of the subtype itself must be static
+
+ b) any inherited predicate must itself be static
+
+I don't think these rules are hard to teach, they seem very straightforward to
+me.
+
+Up in the air
+
+ a) allow AND THEN/OR ELSE with same meaning as AND/OR
+ obviously no side effects are in sight. I don't care
+ on this one.
+
+ b) allow XOR, useless but someone may argue for completeness
+
+This set of rules is easily implementable, and seems quite general enough. I do
+think the inheritance of static predicates is useful, and that means allowing
+AND in any case.
+
+****************************************************************
+
+From: Steve Baird
+Date: Thursday, October 7, 2010 11:31 AM
+
+> Again my set of rules that I proposed is
+>
+> The expression consists of
+>
+> a) ...
+>
+> b) ...
+>
+> c) ...
+>
+> d) recursively expressions allowed by these rules connected
+> by AND or OR or NOT.
+
+and presumably recursively an expression allowed by these rules enclosed in
+parens. Just a nit, but we wouldn't want this left out of the final wording.
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Thursday, October 7, 2010 12:00 PM
+
+...
+> and presumably recursively an expression allowed by these rules
+> enclosed in parens. Just a nit, but we wouldn't want this left out of
+> the final wording.
+
+and presumably qualified expressions where the expression is allowed by these
+rules and the named subtype is static. (Those always go together with
+parenthesized expressions in the wording, and we surely wouldn't want to prevent
+the use for overloading resolution.)
+
+I presume we're not going to include conditional expressions (both if and
+case) here, even if the condition or selector_expression is static. That seems
+like too much work. (Recall that conditional expressions usually work like
+parenthesizes.)
+
+****************************************************************
+
+From: Steve Baird
+Date: Thursday, October 7, 2010 1:02 PM
+
+> and presumably qualified expressions where the expression is allowed
+> by these rules and the named subtype is static. (Those always go
+> together with parenthesized expressions in the wording, and we surely
+> wouldn't want to prevent the use for overloading resolution.)
+>
+
+You may be right, but we need to think about this one (at least briefly).
+
+This introduces the possibility of an exception during the testing of a "static"
+predicate. How do we handle exception-raising values in the coverage rules?
+
+Given
+
+ subtype S is Integer with predicate Natural'(S) not in 123 .. 456;
+
+ X : S := ... ;
+ begin
+ case X is
+
+, what choices need to be covered here? Does the qualified expression play no
+role in determining the set of values that need to be covered, so that in this
+example, we might have
+
+ when Integer'First .. 122 => Foo;
+ when 457 .. Integer'Last => Bar;
+ end case;
+
+?
+
+This shouldn't be a big problem, but, as usual, we need to be sure that
+ a) we know what we want
+ b) the RM wording captures that intent .
+
+> I presume we're not going to include conditional expressions (both if
+> and
+> case) here, even if the condition or selector_expression is static.
+> That seems like too much work. (Recall that conditional expressions
+> usually work like parenthesizes.)
+
+Agreed.
+
+****************************************************************
+
+From: Steve Baird
+Date: Thursday, October 7, 2010 1:04 PM
+
+> and presumably qualified expressions where the expression is allowed
+> by these rules and the named subtype is static.
+
+Could you provide an example illustrating why we would want to allow this?
+
+****************************************************************
+
+From: Robert Dewar
+Date: Thursday, October 7, 2010 1:18 PM
+
+...
+> and presumably recursively an expression allowed by these rules
+> enclosed in parens. Just a nit, but we wouldn't want this left out of
+> the final wording.
+
+Rignt, and a qualified expression as well I would think, the usual special cases
+:-)
+
+****************************************************************
+
+From: Robert Dewar
+Date: Thursday, October 7, 2010 1:19 PM
+
+> I presume we're not going to include conditional expressions (both if
+> and
+> case) here, even if the condition or selector_expression is static.
+> That seems like too much work. (Recall that conditional expressions
+> usually work like parenthesizes.)
+
+I would think that's not worth the effort, but no strong feeling
+
+****************************************************************
+
+From: Robert Dewar
+Date: Thursday, October 7, 2010 1:20 PM
+
+> Could you provide an example illustrating why we would want to allow
+> this?
+
+It just seems that one should ALWAYS be able to qualify expressions without
+affecting things, and that this should be a quite general rule. Probably it is
+not possible to provide a useful example :-)
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Thursday, October 7, 2010 1:26 PM
+
+> Could you provide an example illustrating why we would want to allow
+> this?
+
+Other than consistency with the rest of the language, you mean?
+
+Aspects generally resolve to "any boolean type". That means there is a
+(slight) chance of ambiguity. So I was thinking of something like:
+
+ Boolean'(X /= 10 and X /= 20)
+
+so that the "and" is clearly Boolean and not some other boolean type that might
+be defined with a set of user-defined operators.
+
+But my primary concern was consistency. Generally, a qualified expression is
+allowed anywhere parens are, and it seems wrong to not preserve that, especially
+when ambiguity is possible.
+
+You're right that there is something weird about allowing it directly on the
+subtype name. I'd argue the same applies to parens: why would anyone want to
+write
+ (X) /= 10
+??
+
+So perhaps neither should be allowed directly on the subtype name. (After all,
+we aren't allowing other operators, either, so there isn't anything to be
+consistent with here -- the rules are what we make them.)
+
+What I think is important is that:
+
+ with predicate => X /= 10 and X /= 20
+
+and
+
+ with predicate => (X /= 10) and (X /= 20)
+
+and
+
+ when predicate => Boolean'(X /= 10) and Boolean'(X /= 20)
+
+all work the same, because they *are* the same to any experienced Ada
+programmer.
+
+****************************************************************
+
+From: Tucker Taft
+Date: Thursday, October 7, 2010 1:27 PM
+
+I don't think we should allow a qualified expression to be applied to the
+subtype name. That is unnecessary complexity, since the subtype name is not
+overloadable. I wouldn't allow it to be applied to any expression containing the
+subtype name. Any expression *not* containing the subtype name should allow
+anything at all, so long as it is a static expression. So I don't agree with
+the idea of allowing qualified expressions anywhere we allow parentheses. Ditto
+for conversions, and other complexities. As soon as the subtype name gets
+involved in the expression, there should be very tight limits.
+
+****************************************************************
+
+From: Robert Dewar
+Date: Thursday, October 7, 2010 1:45 PM
+
+> What I think is important is that:
+>
+> with predicate => X /= 10 and X /= 20
+>
+> and
+>
+> with predicate => (X /= 10) and (X /= 20)
+>
+> and
+>
+> when predicate => Boolean'(X /= 10) and Boolean'(X /= 20)
+>
+> all work the same, because they*are* the same to any experienced Ada
+> programmer.
+
+I agree with this, and it is trivial to implement
+
+****************************************************************
+
+From: Robert Dewar
+Date: Thursday, October 7, 2010 1:49 PM
+
+> I don't think we should allow a qualified expression to be applied to
+> the subtype name. That is unnecessary complexity, since the subtype
+> name is not overloadable.
+> I wouldn't allow it to be applied to any expression containing the
+> subtype name. Any expression *not* containing the subtype name should
+> allow anything at all, so long as it is a static expression. So I
+> don't agree with the idea of allowing qualified expressions anywhere
+> we allow parentheses. Ditto for conversions, and other complexities.
+> As soon as the subtype name gets involved in the expression, there
+> should be very tight limits.
+
+I agree that parenthesizing the subtype name is silly, but I see no reason not
+to allow qualification of expressions containing it like Boolean'(S > 12).
+
+****************************************************************
+
+From: Tucker Taft
+Date: Thursday, October 7, 2010 1:50 PM
+
+A useful property of membership, comparison, logical ops, and parentheses, is
+that there is no possibility for failure. Allowing a qualified expression to be
+applied to an expression involving the subtype name (current instance) would
+introduce the possibility of raising an exception, which definitely adds
+unnecessary complexity. I think we should limit ourselves to never-failing
+operations for the parts which are non-static expressions, namely the operations
+having the subtype current instance as an operand or sub-operand.
+
+****************************************************************
+
+
+
Questions? Ask the ACAA Technical Agent