comp.lang.ada
 help / color / mirror / Atom feed
* Non_Primitive Operations and Object.Operation Resolution
@ 2016-04-20 23:59 Jeffrey R. Carter
  2016-04-21 20:28 ` Randy Brukardt
  2016-04-22 23:49 ` ytomino
  0 siblings, 2 replies; 9+ messages in thread
From: Jeffrey R. Carter @ 2016-04-20 23:59 UTC (permalink / raw)


Some pertinent code from PragmARC.Unbounded_Integers:

package PragmARC.Unbounded_Integers is
    ...
private -- PragmARC.Unbounded_Integers
    type Calculation_Value is mod System.Max_Binary_Modulus;

    Digit_Size : constant := Calculation_Value'Size / 2;

    type Digit_Value is mod 2 ** Digit_Size;

    package Digit_Lists is new Ada.Containers.Vectors (Index_Type => Positive, 
Element_Type => Digit_Value);

    subtype Digit_List is Digit_Lists.Vector;
    ...
end PragmARC.Unbounded_Integers;

package body PragmARC.Unbounded_Integers is
    ...
    use type Digit_List;

    function Element (List : Digit_List; Index : Positive) return Digit_Value;
    -- If Index is a valid index into List, returns the value stored there; 
otherwise, returns 0
    ...
    ... List.Element (Index) ... -- Index is known to be a valid index for List
    ...
    ... Element (Left.Digit, I) ... I may not be a valid index for Left.Digit

Until recently, this was no problem. Calls like the 1st example called the 
primitive Element declared in Digit_Lists. Calls like the 2nd called the 
non-primitive Element declared in Unbounded_Integers, the only one directly visible.

Recently I've received a couple of reports that this code fails to compile with 
GNAT GPL 2015. It complains, for calls like List.Element, that it can't resolve 
Element, pointing to the primitive one in Digit_Lists and the non-primitive one 
in Unbounded_Integers. I dismissed this as a compiler error, since 
Object.Operation notation may only be used for primitive operations.

However, I've more recently been informed that "gcc 6" on FreeBSD gives the same 
error. While I still think this is a compiler error, I thought I'd ask the 
language lawyers and ARG members on here to make sure.

Note that Unbounded_Integers is written to ISO/IEC 8652:2007, and so may not 
compile with an Ada-12 compiler. For GNAT, that means it should be compiled with 
the -gnat05 option. However, I see no reason why it should not also be valid Ada 
12, and it was reported that ggc 6 gives the same error with or without that option.

-- 
Jeff Carter
"[M]any were collected near them, ... to
enjoy the sight of a dead young lady, nay,
two dead young ladies, for it proved twice
as fine as the first report."
Persuasion
155

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Non_Primitive Operations and Object.Operation Resolution
  2016-04-20 23:59 Non_Primitive Operations and Object.Operation Resolution Jeffrey R. Carter
@ 2016-04-21 20:28 ` Randy Brukardt
  2016-04-21 21:13   ` Jeffrey R. Carter
  2016-04-22 23:49 ` ytomino
  1 sibling, 1 reply; 9+ messages in thread
From: Randy Brukardt @ 2016-04-21 20:28 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:nf94tt$9iv$1@dont-email.me...
> Some pertinent code from PragmARC.Unbounded_Integers:
>
> package PragmARC.Unbounded_Integers is
>    ...
> private -- PragmARC.Unbounded_Integers
>    type Calculation_Value is mod System.Max_Binary_Modulus;
>
>    Digit_Size : constant := Calculation_Value'Size / 2;
>
>    type Digit_Value is mod 2 ** Digit_Size;
>
>    package Digit_Lists is new Ada.Containers.Vectors (Index_Type => 
> Positive, Element_Type => Digit_Value);
>
>    subtype Digit_List is Digit_Lists.Vector;
>    ...
> end PragmARC.Unbounded_Integers;
>
> package body PragmARC.Unbounded_Integers is
>    ...
>    use type Digit_List;
>
>    function Element (List : Digit_List; Index : Positive) return 
> Digit_Value;
>    -- If Index is a valid index into List, returns the value stored there; 
> otherwise, returns 0
>    ...
>    ... List.Element (Index) ... -- Index is known to be a valid index for 
> List
>    ...
>    ... Element (Left.Digit, I) ... I may not be a valid index for 
> Left.Digit
>
> Until recently, this was no problem. Calls like the 1st example called the 
> primitive Element declared in Digit_Lists. Calls like the 2nd called the 
> non-primitive Element declared in Unbounded_Integers, the only one 
> directly visible.
>
> Recently I've received a couple of reports that this code fails to compile 
> with GNAT GPL 2015. It complains, for calls like List.Element, that it 
> can't resolve Element, pointing to the primitive one in Digit_Lists and 
> the non-primitive one in Unbounded_Integers. I dismissed this as a 
> compiler error, since Object.Operation notation may only be used for 
> primitive operations.

Humm. I would have agreed with you without looking it up, but that's not 
what the wording of 4.1.3 says. It says that "The selector_name shall 
resolve to denote a view of a subprogram declared immediately within the 
declarative region in which an ancestor of the type T is declared." It then 
goes on to make requirements on the first formal parameter of the subprogram 
(to be T, AT'Class, access T, or access AT'Class, where AT is some ancestor 
of T, [recall that "ancestor of T" includes T itself).

Your second function Element certainly qualifies on the secondary rules. I 
would think that it does *not* qualify on the "declarative region" part of 
the rule, but since this isn't your actual code [which is likely to be 
subtly different], I can't say that for sure. If the declarative region of 
some ancestor type of  Digit_Lists includes your second function Element, 
then the call should be ambiguous. (The declarative region includes any 
bodies, so putting the subprogram in the body doesn't change anything.)

If Digit_List has been a derived type, then this Element routine would 
surely qualify (and the call would be ambiguous - although I'm not sure that 
the subprogram would even be legal, as it would be a non-overriding 
homograph of an inherited routine -- that's a rabbit hole I'm not going down 
now as it's not really related to your question).

Assuming that there isn't anything sneaky in the part of the code that you 
didn't provide, it appears to me that GNAT is treating the subtype as one of 
the ancestors which determines the declarative region. I don't think that 
was the intent of the rule, but I can't say for sure. (Is a subtype of T an 
"ancestor of T"? Dunno). The original idea was primitives and class-wides, 
and subtypes don't really fit into that, but the actual wording is what 
matters most.

I just checked the ACATS tests, and I don't see any that would insist on the 
subtype being considered. (But I only checked tests for 4.1.3; sometimes 
some unrelated test touches some corner case.)

If you would like, I could take this to the ARG and see if anyone has any 
insight.

> However, I've more recently been informed that "gcc 6" on FreeBSD gives 
> the same error. While I still think this is a compiler error, I thought 
> I'd ask the language lawyers and ARG members on here to make sure.
>
> Note that Unbounded_Integers is written to ISO/IEC 8652:2007, and so may 
> not compile with an Ada-12 compiler. For GNAT, that means it should be 
> compiled with the -gnat05 option. However, I see no reason why it should 
> not also be valid Ada 12, and it was reported that ggc 6 gives the same 
> error with or without that option.

The wording in question was originally in ISO/IEC 8652:2007; it was changed 
in Ada 2012 but the change is pedantic (having to do with ignoring 
implicitly declared overridden primitives) and doesn't seem to have anything 
to do with this question.

In any case, your code is unnecessarily fragile, as even if GNAT is wrong in 
this particular instance, future program maintenance could make the GNAT 
behavior correct. I'd suggest giving the non-primitive Element a different 
name -- less convinient, perhaps, but if you do that you don't have visit 
grey areas in the RM. :-)

                                               Randy. 



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Non_Primitive Operations and Object.Operation Resolution
  2016-04-21 20:28 ` Randy Brukardt
@ 2016-04-21 21:13   ` Jeffrey R. Carter
  2016-04-22  6:27     ` AdaMagica
  2016-04-22 22:24     ` Randy Brukardt
  0 siblings, 2 replies; 9+ messages in thread
From: Jeffrey R. Carter @ 2016-04-21 21:13 UTC (permalink / raw)


On 04/21/2016 01:28 PM, Randy Brukardt wrote:
>
> Humm. I would have agreed with you without looking it up, but that's not
> what the wording of 4.1.3 says. It says that "The selector_name shall
> resolve to denote a view of a subprogram declared immediately within the
> declarative region in which an ancestor of the type T is declared." It then
> goes on to make requirements on the first formal parameter of the subprogram
> (to be T, AT'Class, access T, or access AT'Class, where AT is some ancestor
> of T, [recall that "ancestor of T" includes T itself).

T is Digits_Lists.Vector. I don't see any way that Unbounded_Integers.Element 
could be in the declarative region of that (Digit_Lists) or of any ancestor 
(such as Ada.Finalization.Controlled).

> Your second function Element certainly qualifies on the secondary rules. I
> would think that it does *not* qualify on the "declarative region" part of
> the rule, but since this isn't your actual code [which is likely to be
> subtly different], I can't say that for sure. If the declarative region of
> some ancestor type of  Digit_Lists includes your second function Element,
> then the call should be ambiguous. (The declarative region includes any
> bodies, so putting the subprogram in the body doesn't change anything.)

What I provided is the actual code, just not /all/ of the actual code. I don't 
see anything in the full code that would make the pkg body be part of the 
declarative region of the type or any ancestor. I can provide the full pkg, or 
you can obtain it from pragmada.x10hosting.com or 
https://github.com/jrcarter/PragmARC

> If you would like, I could take this to the ARG and see if anyone has any
> insight.

That would probably be a good idea. Subtypes are not types and I'd think should 
not be considered an ancestor of the type. Considering a subtype as an ancestor 
seems like it would be a disaster.

> In any case, your code is unnecessarily fragile, as even if GNAT is wrong in
> this particular instance, future program maintenance could make the GNAT
> behavior correct. I'd suggest giving the non-primitive Element a different
> name -- less convinient, perhaps, but if you do that you don't have visit
> grey areas in the RM. :-)

Perhaps. Element seemed the best name at the time, given my limited 
understanding of the language.

-- 
Jeff Carter
"I was either in love, or I had smallpox."
Take the Money and Run
137


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Non_Primitive Operations and Object.Operation Resolution
  2016-04-21 21:13   ` Jeffrey R. Carter
@ 2016-04-22  6:27     ` AdaMagica
  2016-04-22 18:24       ` Jeffrey R. Carter
  2016-04-22 22:24     ` Randy Brukardt
  1 sibling, 1 reply; 9+ messages in thread
From: AdaMagica @ 2016-04-22  6:27 UTC (permalink / raw)


Am Donnerstag, 21. April 2016 23:13:19 UTC+2 schrieb Jeffrey R. Carter:
> That would probably be a good idea. Subtypes are not types and I'd think should 
> not be considered an ancestor of the type. Considering a subtype as an ancestor 
> seems like it would be a disaster.

Only, subtypes have names, the type of a subtype is anonymous. What you see in a type declaration is the first subtype.

Don't know whether this is related to your problen - just to corret the nomenclature.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Non_Primitive Operations and Object.Operation Resolution
  2016-04-22  6:27     ` AdaMagica
@ 2016-04-22 18:24       ` Jeffrey R. Carter
  0 siblings, 0 replies; 9+ messages in thread
From: Jeffrey R. Carter @ 2016-04-22 18:24 UTC (permalink / raw)


On 04/21/2016 11:27 PM, AdaMagica wrote:
> Am Donnerstag, 21. April 2016 23:13:19 UTC+2 schrieb Jeffrey R. Carter:
>> That would probably be a good idea. Subtypes are not types and I'd think should
>> not be considered an ancestor of the type. Considering a subtype as an ancestor
>> seems like it would be a disaster.
>
> Only, subtypes have names, the type of a subtype is anonymous. What you see in a type declaration is the first subtype.
>
> Don't know whether this is related to your problen - just to corret the nomenclature.

Yes. However, the definition of "ancestor" uses the term "type", not "subtype".

-- 
Jeff Carter
"Go and boil your bottoms."
Monty Python & the Holy Grail
01


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Non_Primitive Operations and Object.Operation Resolution
  2016-04-21 21:13   ` Jeffrey R. Carter
  2016-04-22  6:27     ` AdaMagica
@ 2016-04-22 22:24     ` Randy Brukardt
  2016-04-23  0:37       ` Jeffrey R. Carter
  1 sibling, 1 reply; 9+ messages in thread
From: Randy Brukardt @ 2016-04-22 22:24 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:nfbfj0$1m2$1@dont-email.me...
> On 04/21/2016 01:28 PM, Randy Brukardt wrote:
...
>> If you would like, I could take this to the ARG and see if anyone has any
>> insight.
>
> That would probably be a good idea. Subtypes are not types and I'd think 
> should not be considered an ancestor of the type. Considering a subtype as 
> an ancestor seems like it would be a disaster.

I've sent the question to the ARG. But I don't see any "disaster" even if 
the subtype is included; there shouldn't be routines with the same name and 
profile sitting around to get picked up anyway.

>> In any case, your code is unnecessarily fragile, as even if GNAT is wrong 
>> in
>> this particular instance, future program maintenance could make the GNAT
>> behavior correct. I'd suggest giving the non-primitive Element a 
>> different
>> name -- less convinient, perhaps, but if you do that you don't have visit
>> grey areas in the RM. :-)
>
> Perhaps. Element seemed the best name at the time, given my limited 
> understanding of the language.

My view is that anytime you have more than one visible (note: not 
necessarily *directly* visible) entity with the same name and same profile, 
but has different semantics, you have unnecessarily tricky code, regardless 
of the legality of that code. A reader of the code could very well refer to 
the wrong declaration (programmers are not great at figuring out the nuances 
of Ada visibility rules), and that could lead to problems during program 
maintance (especially if that maintenance is done by someone other than the 
original author). As such, I'd suggest that the routine in the body be named 
something like Safe_Element just to reduce this potential confusion. (I know 
*I* could very well use the wrong routine in debugging this package.)

Still, legal Ada code ought to compile. even when it isn't a good idea. :-)

                                       Randy.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Non_Primitive Operations and Object.Operation Resolution
  2016-04-20 23:59 Non_Primitive Operations and Object.Operation Resolution Jeffrey R. Carter
  2016-04-21 20:28 ` Randy Brukardt
@ 2016-04-22 23:49 ` ytomino
  2016-04-23  0:38   ` Jeffrey R. Carter
  1 sibling, 1 reply; 9+ messages in thread
From: ytomino @ 2016-04-22 23:49 UTC (permalink / raw)


I think It's a bug of the compiler.

I tried to move the prototype of Element from body to spec.
Then, I got success to compile it with gcc-6.0.0-20160401.


--- pragmarc-unbounded_integers.ads.orig	2016-04-23 08:45:44.000000000 +0900
+++ pragmarc-unbounded_integers.ads	2016-04-23 08:46:12.000000000 +0900
@@ -72,6 +72,10 @@
       Negative : Boolean    := False;
       Digit    : Digit_List := Single_Zero;
    end record;
+
+   function Element (List : Digit_List; Index : Positive) return Digit_Value;
+   -- If Index is a valid index into List, returns the value stored there; otherwise, returns 0
+
 end PragmARC.Unbounded_Integers;
 --
 -- This is free software; you can redistribute it and/or modify it under

--- pragmarc-unbounded_integers.adb.orig	2016-04-23 08:45:48.000000000 +0900
+++ pragmarc-unbounded_integers.adb	2016-04-23 08:46:08.000000000 +0900
@@ -14,9 +14,6 @@
 
    use type Digit_List;
 
-   function Element (List : Digit_List; Index : Positive) return Digit_Value;
-   -- If Index is a valid index into List, returns the value stored there; otherwise, returns 0
-
    procedure Insert (List : in out Digit_List; Index : in Positive; Value : in Digit_Value);
    -- If Index is a valid index into List, replaces the digit at Index with Value;
    -- otherwise, appends zeros to List until Index - 1 is a valid index, then appends Value to List


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Non_Primitive Operations and Object.Operation Resolution
  2016-04-22 22:24     ` Randy Brukardt
@ 2016-04-23  0:37       ` Jeffrey R. Carter
  0 siblings, 0 replies; 9+ messages in thread
From: Jeffrey R. Carter @ 2016-04-23  0:37 UTC (permalink / raw)


On 04/22/2016 03:24 PM, Randy Brukardt wrote:
>
> My view is that anytime you have more than one visible (note: not
> necessarily *directly* visible) entity with the same name and same profile,
> but has different semantics, you have unnecessarily tricky code, regardless
> of the legality of that code. A reader of the code could very well refer to
> the wrong declaration (programmers are not great at figuring out the nuances
> of Ada visibility rules), and that could lead to problems during program
> maintance (especially if that maintenance is done by someone other than the
> original author). As such, I'd suggest that the routine in the body be named
> something like Safe_Element just to reduce this potential confusion. (I know
> *I* could very well use the wrong routine in debugging this package.)

It seems clear to me, but I guess I'm weird. Generic iterators (which I've been 
using since Ada 83 was the current version) seem clear to me, but I recall 
reading somewhere that some ARG members found them confusing.

> Still, legal Ada code ought to compile. even when it isn't a good idea. :-)

Absolutely.

-- 
Jeff Carter
"Go and boil your bottoms."
Monty Python & the Holy Grail
01

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Non_Primitive Operations and Object.Operation Resolution
  2016-04-22 23:49 ` ytomino
@ 2016-04-23  0:38   ` Jeffrey R. Carter
  0 siblings, 0 replies; 9+ messages in thread
From: Jeffrey R. Carter @ 2016-04-23  0:38 UTC (permalink / raw)


On 04/22/2016 04:49 PM, ytomino wrote:
> I think It's a bug of the compiler.
>
> I tried to move the prototype of Element from body to spec.
> Then, I got success to compile it with gcc-6.0.0-20160401.

That does seem indicative of a compiler error. Where the declaration appears 
shouldn't make a difference.

-- 
Jeff Carter
"Go and boil your bottoms."
Monty Python & the Holy Grail
01


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-04-23  0:38 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-20 23:59 Non_Primitive Operations and Object.Operation Resolution Jeffrey R. Carter
2016-04-21 20:28 ` Randy Brukardt
2016-04-21 21:13   ` Jeffrey R. Carter
2016-04-22  6:27     ` AdaMagica
2016-04-22 18:24       ` Jeffrey R. Carter
2016-04-22 22:24     ` Randy Brukardt
2016-04-23  0:37       ` Jeffrey R. Carter
2016-04-22 23:49 ` ytomino
2016-04-23  0:38   ` Jeffrey R. Carter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox