comp.lang.ada
 help / color / mirror / Atom feed
* Ada Alternatives to Unrestricted_Access
@ 2018-03-07 20:11 Jere
  2018-03-07 20:38 ` Dmitry A. Kazakov
                   ` (2 more replies)
  0 siblings, 3 replies; 27+ messages in thread
From: Jere @ 2018-03-07 20:11 UTC (permalink / raw)


I'm currently updating a generic package that takes a container type
as an input and creates an iterative type around it.  I found quite a
few instances of GNAT's Unrestricted_Access which appear to be
necessary because of the Iterate function's container parameter of
being mode "in" and the iterator needing a non constant access to it
to supply tamper check semantics.  I tried changing the mode to
"in out" but that caused a slew of errors where Iterate was used 
inside other operations that had the Container supplied via "in"
mode parameters.  Changing those other operations doesn't make
sense (and causes other errors later), but I don't like relying
on GNAT's implementation defined attribute if I can help it.

I was able to use System.Address_To_Access_Conversions to 
achieve both compiler happiness and expected runtime execution, but
I am worried this is not legal as it is skirting kind of close
to Address overlays.  In this case the types are identical aside
from one (the Iterate "in" mode parameter) being constant and the
other (the iterators "Container_Access" component) being variable.
However, I am not fully convinced it is (relatively) safe or portable yet.

The gist of the differences being:

   Container_Access => C'Unrestricted_Access

is converted to:

   Container_Access => A2A.To_Pointer(C'Address)

where:
   
   package A2A is new System.Address_To_Access_Conversions(Container);

and the parameter mode of C is defined as:

   function Iterate
            (C : in Container)
             return Iterator_Interfaces.Forward_Iterator'Class;

and the generic formal for Container

   type Container is tagged private;

I'm working with an existing code base, so complete overhaul is 
not a great option.

If it isn't a good idea, are there alternatives?  Since the Container
implementation is unknown in the generic, I wasn't able to get a version
of the Rosen technique to work as an alternative (same constant vs
variable access problem).


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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-07 20:11 Ada Alternatives to Unrestricted_Access Jere
@ 2018-03-07 20:38 ` Dmitry A. Kazakov
  2018-03-07 22:29   ` Jere
  2018-03-08  3:18 ` gautier_niouzes
  2018-03-08 17:51 ` Jeffrey R. Carter
  2 siblings, 1 reply; 27+ messages in thread
From: Dmitry A. Kazakov @ 2018-03-07 20:38 UTC (permalink / raw)


On 2018-03-07 21:11, Jere wrote:

>     function Iterate
>              (C : in Container)
>               return Iterator_Interfaces.Forward_Iterator'Class;
> 
> and the generic formal for Container
> 
>     type Container is tagged private;
> 
> I'm working with an existing code base, so complete overhaul is
> not a great option.
> 
> If it isn't a good idea, are there alternatives?

[...]

> Since the Container
> implementation is unknown in the generic, I wasn't able to get a version
> of the Rosen technique to work as an alternative (same constant vs
> variable access problem).

I am not sure I understand the problem. Why don't you pass a function 
Self along with the container type:

    generic
       type Container is tagged whatever;
       function Self (C : Container'Class)
          return not null access Container'Class;
    package Iterative_Mess is

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-07 20:38 ` Dmitry A. Kazakov
@ 2018-03-07 22:29   ` Jere
  2018-03-08  8:27     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 27+ messages in thread
From: Jere @ 2018-03-07 22:29 UTC (permalink / raw)


On Wednesday, March 7, 2018 at 3:38:13 PM UTC-5, Dmitry A. Kazakov wrote:
> On 2018-03-07 21:11, Jere wrote:
> 
> >     function Iterate
> >              (C : in Container)
> >               return Iterator_Interfaces.Forward_Iterator'Class;
> > 
> > and the generic formal for Container
> > 
> >     type Container is tagged private;
> > 
> > I'm working with an existing code base, so complete overhaul is
> > not a great option.
> > 
> > If it isn't a good idea, are there alternatives?
> 
> [...]
> 
> > Since the Container
> > implementation is unknown in the generic, I wasn't able to get a version
> > of the Rosen technique to work as an alternative (same constant vs
> > variable access problem).
> 
> I am not sure I understand the problem. Why don't you pass a function 
> Self along with the container type:
> 
>     generic
>        type Container is tagged whatever;
>        function Self (C : Container'Class)
>           return not null access Container'Class;
>     package Iterative_Mess is
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

Because the package is already in use in other code, so
changing the specification would be a very time consuming
change.  I was just trying to get rid of the
Unrestricted_Access if I could and was asking if
using Address_To_Access_Conversions was an ok way to
do so (is it portable Ada, and is it defined behavior) OR
if there was a different alternative.


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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-07 20:11 Ada Alternatives to Unrestricted_Access Jere
  2018-03-07 20:38 ` Dmitry A. Kazakov
@ 2018-03-08  3:18 ` gautier_niouzes
  2018-03-09  0:41   ` Jere
  2018-03-08 17:51 ` Jeffrey R. Carter
  2 siblings, 1 reply; 27+ messages in thread
From: gautier_niouzes @ 2018-03-08  3:18 UTC (permalink / raw)


I had the same problem for GL[U[T]] bindings (work on both GNAT and ObjectAda, and perhaps other Ada systems) [1]. A quick search with AZip (shameless plug :-) [2] leads to 
  package A2A_double is new System.Address_To_Access_Conversions(Double);
...
  procedure Vertex (v: Double_Vector_3D) is
  begin
    Vertex3dv(A2A_double.To_Pointer(v(0)'Address));
    -- This method is functionally identical
    -- to using GNAT's 'Unrestricted_Access
  end Vertex;

Other places use an Unchecked_Conversion.
The GNAT doc says:
"The Unrestricted_Access attribute is similar to Access except that all accessibility and aliased view checks are omitted. This is a user-beware attribute. It is similar to Address, for which it is a desirable replacement where the value desired is an access type. In other words, its effect is identical to first applying the Address attribute and then doing an unchecked conversion to a desired access type."

___

[1] https://globe3d.sourceforge.io/
[2] https://azip.sourceforge.io/

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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-07 22:29   ` Jere
@ 2018-03-08  8:27     ` Dmitry A. Kazakov
  2018-03-09  0:43       ` Jere
  0 siblings, 1 reply; 27+ messages in thread
From: Dmitry A. Kazakov @ 2018-03-08  8:27 UTC (permalink / raw)


On 07/03/2018 23:29, Jere wrote:
> On Wednesday, March 7, 2018 at 3:38:13 PM UTC-5, Dmitry A. Kazakov wrote:
>> On 2018-03-07 21:11, Jere wrote:

>>> Since the Container
>>> implementation is unknown in the generic, I wasn't able to get a version
>>> of the Rosen technique to work as an alternative (same constant vs
>>> variable access problem).
>>
>> I am not sure I understand the problem. Why don't you pass a function
>> Self along with the container type:
>>
>>      generic
>>         type Container is tagged whatever;
>>         function Self (C : Container'Class)
>>            return not null access Container'Class;
>>      package Iterative_Mess is
> 
> Because the package is already in use in other code, so
> changing the specification would be a very time consuming
> change.

You can default Self when not used.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-07 20:11 Ada Alternatives to Unrestricted_Access Jere
  2018-03-07 20:38 ` Dmitry A. Kazakov
  2018-03-08  3:18 ` gautier_niouzes
@ 2018-03-08 17:51 ` Jeffrey R. Carter
  2018-03-09  0:36   ` Jere
  2 siblings, 1 reply; 27+ messages in thread
From: Jeffrey R. Carter @ 2018-03-08 17:51 UTC (permalink / raw)


On 03/07/2018 09:11 PM, Jere wrote:
> 
>     function Iterate
>              (C : in Container)
>               return Iterator_Interfaces.Forward_Iterator'Class;
> 
> and the generic formal for Container
> 
>     type Container is tagged private;

Since Container is tagged, the parameter C should be aliased [ARM 3.10(9)], so 
you should be able to use 'Unchecked_Access. Or am I missing something?

-- 
Jeff Carter
"I've got to stay here, but there's no reason
why you folks shouldn't go out into the lobby
until this thing blows over."
Horse Feathers
50


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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-08 17:51 ` Jeffrey R. Carter
@ 2018-03-09  0:36   ` Jere
  2018-03-09 16:46     ` Jeffrey R. Carter
  0 siblings, 1 reply; 27+ messages in thread
From: Jere @ 2018-03-09  0:36 UTC (permalink / raw)


On Thursday, March 8, 2018 at 12:51:02 PM UTC-5, Jeffrey R. Carter wrote:
> On 03/07/2018 09:11 PM, Jere wrote:
> > 
> >     function Iterate
> >              (C : in Container)
> >               return Iterator_Interfaces.Forward_Iterator'Class;
> > 
> > and the generic formal for Container
> > 
> >     type Container is tagged private;
> 
> Since Container is tagged, the parameter C should be aliased [ARM 3.10(9)], so 
> you should be able to use 'Unchecked_Access. Or am I missing something?
> 
> -- 
> Jeff Carter
> "I've got to stay here, but there's no reason
> why you folks shouldn't go out into the lobby
> until this thing blows over."
> Horse Feathers
> 50

It generates the error "access-to-variable designates constant" because
the function takes a parameter of mode "in" while the iterator needs
a non-constant access to the variable.  I can't change the mode of the
function for other reasons.

I checked the definition of Unchecked_Access (13.10) and it only addresses 
the accessibility restrictions on taking 'Access:
13.10 [3]
All rules and semantics that apply to X'Access (see 3.10.2) apply also to X'Unchecked_Access, except that, for the purposes of accessibility rules and checks, it is as if X were declared immediately within a library package.

Keep in mind I am not having trouble getting past the Accessibility level, 
I am having trouble getting past the "const"ed-ness of the parameter since
it needs to be of mode "in" to work with user defined iteration.

If you look at the vector implementation in GNAT, you'll see that in the
iterate function they have to use Unrestricted_Access for the same reason.
I was just hoping for a more ada portable method.  



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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-08  3:18 ` gautier_niouzes
@ 2018-03-09  0:41   ` Jere
  0 siblings, 0 replies; 27+ messages in thread
From: Jere @ 2018-03-09  0:41 UTC (permalink / raw)


On Wednesday, March 7, 2018 at 10:18:47 PM UTC-5, gautier wrote:
> I had the same problem for GL[U[T]] bindings (work on both GNAT and ObjectAda, and perhaps other Ada systems) [1]. A quick search with AZip (shameless plug :-) [2] leads to 
>   package A2A_double is new System.Address_To_Access_Conversions(Double);
> ...
>   procedure Vertex (v: Double_Vector_3D) is
>   begin
>     Vertex3dv(A2A_double.To_Pointer(v(0)'Address));
>     -- This method is functionally identical
>     -- to using GNAT's 'Unrestricted_Access
>   end Vertex;
> 
> Other places use an Unchecked_Conversion.
> The GNAT doc says:
> "The Unrestricted_Access attribute is similar to Access except that all accessibility and aliased view checks are omitted. This is a user-beware attribute. It is similar to Address, for which it is a desirable replacement where the value desired is an access type. In other words, its effect is identical to first applying the Address attribute and then doing an unchecked conversion to a desired access type."
> 
> ___
> 
> [1] https://globe3d.sourceforge.io/
> [2] https://azip.sourceforge.io/

Yep, that's basically the same conclusion I came to.  My doubts center
around whether it is legit in portable Ada to do so to bypass the "in"
mode.  I don't know if the language allows for a compiler to use
different representations for a constant variable and a mutable variable.
If so, what I am doing might possibly be erroneous behavior.  It would
work in GNAT based on the section you quoted, but I was curious if
it would run afoul in other compilers possibly.

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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-08  8:27     ` Dmitry A. Kazakov
@ 2018-03-09  0:43       ` Jere
  2018-03-09  0:52         ` Jere
  0 siblings, 1 reply; 27+ messages in thread
From: Jere @ 2018-03-09  0:43 UTC (permalink / raw)


On Thursday, March 8, 2018 at 3:27:02 AM UTC-5, Dmitry A. Kazakov wrote:
> On 07/03/2018 23:29, Jere wrote:
> > On Wednesday, March 7, 2018 at 3:38:13 PM UTC-5, Dmitry A. Kazakov wrote:
> >> On 2018-03-07 21:11, Jere wrote:
> 
> >>> Since the Container
> >>> implementation is unknown in the generic, I wasn't able to get a version
> >>> of the Rosen technique to work as an alternative (same constant vs
> >>> variable access problem).
> >>
> >> I am not sure I understand the problem. Why don't you pass a function
> >> Self along with the container type:
> >>
> >>      generic
> >>         type Container is tagged whatever;
> >>         function Self (C : Container'Class)
> >>            return not null access Container'Class;
> >>      package Iterative_Mess is
> > 
> > Because the package is already in use in other code, so
> > changing the specification would be a very time consuming
> > change.
> 
> You can default Self when not used.
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

So I tried playing with this, but I still ran into the same
problem when trying to implement the Self function.  Inside
I needed to "un-const" the container, so I came back to this
same problem.

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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-09  0:43       ` Jere
@ 2018-03-09  0:52         ` Jere
  2018-03-09  8:28           ` Dmitry A. Kazakov
  0 siblings, 1 reply; 27+ messages in thread
From: Jere @ 2018-03-09  0:52 UTC (permalink / raw)


On Thursday, March 8, 2018 at 7:43:31 PM UTC-5, Jere wrote:
> On Thursday, March 8, 2018 at 3:27:02 AM UTC-5, Dmitry A. Kazakov wrote:
> > On 07/03/2018 23:29, Jere wrote:
> > > On Wednesday, March 7, 2018 at 3:38:13 PM UTC-5, Dmitry A. Kazakov wrote:
> > >> On 2018-03-07 21:11, Jere wrote:
> > 
> > >>> Since the Container
> > >>> implementation is unknown in the generic, I wasn't able to get a version
> > >>> of the Rosen technique to work as an alternative (same constant vs
> > >>> variable access problem).
> > >>
> > >> I am not sure I understand the problem. Why don't you pass a function
> > >> Self along with the container type:
> > >>
> > >>      generic
> > >>         type Container is tagged whatever;
> > >>         function Self (C : Container'Class)
> > >>            return not null access Container'Class;
> > >>      package Iterative_Mess is
> > > 
> > > Because the package is already in use in other code, so
> > > changing the specification would be a very time consuming
> > > change.
> > 
> > You can default Self when not used.
> > 
> > -- 
> > Regards,
> > Dmitry A. Kazakov
> > http://www.dmitry-kazakov.de
> 
> So I tried playing with this, but I still ran into the same
> problem when trying to implement the Self function.  Inside
> I needed to "un-const" the container, so I came back to this
> same problem.

Example:
with Ada.Text_IO; use Ada.Text_IO;
with System.Address_To_Access_Conversions;

procedure jdoodle is
    type Container is tagged null record;
    
    package A2A is new System.Address_To_Access_Conversions(Container);
    
    type Container_Access is access Container;
    type Container_Constant_Access is access constant Container;
    
    function Self 
        (C : Container'Class)
         return not null access Container'Class
    is begin
        --return C'Unchecked_Access;  --ERROR: access-to-variable designates constant
        --return C'Unrestricted_Access;  -- Works, but not portable, GNAT specific
        return A2A.To_Pointer(C'Address);  -- Also works, unsure if OK in portable Ada
    end Self;
     
begin
    null;
end jdoodle;


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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-09  0:52         ` Jere
@ 2018-03-09  8:28           ` Dmitry A. Kazakov
  2018-03-11  0:31             ` Jere
  0 siblings, 1 reply; 27+ messages in thread
From: Dmitry A. Kazakov @ 2018-03-09  8:28 UTC (permalink / raw)


On 09/03/2018 01:52, Jere wrote:

> Example:
> with Ada.Text_IO; use Ada.Text_IO;
> with System.Address_To_Access_Conversions;
> 
> procedure jdoodle is
>      type Container is tagged null record;

Do you have control over Container? Can you derive from? Can you put it 
into a wrapper type or use a handle to the container in the generic 
instead of container itself.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-09  0:36   ` Jere
@ 2018-03-09 16:46     ` Jeffrey R. Carter
  2018-03-11  0:38       ` Jere
  0 siblings, 1 reply; 27+ messages in thread
From: Jeffrey R. Carter @ 2018-03-09 16:46 UTC (permalink / raw)


On 03/09/2018 01:36 AM, Jere wrote:
> 
> It generates the error "access-to-variable designates constant" because
> the function takes a parameter of mode "in" while the iterator needs
> a non-constant access to the variable.  I can't change the mode of the
> function for other reasons.

OK, that's what I missed. I guess you could unchecked convert from 
access-constant to access-all.

-- 
Jeff Carter
"To Err is human, to really screw up, you need C++!"
Stéphane Richard
63

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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-09  8:28           ` Dmitry A. Kazakov
@ 2018-03-11  0:31             ` Jere
  0 siblings, 0 replies; 27+ messages in thread
From: Jere @ 2018-03-11  0:31 UTC (permalink / raw)


On Friday, March 9, 2018 at 3:28:43 AM UTC-5, Dmitry A. Kazakov wrote:
> On 09/03/2018 01:52, Jere wrote:
> 
> > Example:
> > with Ada.Text_IO; use Ada.Text_IO;
> > with System.Address_To_Access_Conversions;
> > 
> > procedure jdoodle is
> >      type Container is tagged null record;
> 
> Do you have control over Container? Can you derive from? Can you put it 
> into a wrapper type or use a handle to the container in the generic 
> instead of container itself.
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

Not practically.  I'm not really allowed to change any of the specs
and there is already a lot of code using the existing containers and
the generic.


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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-09 16:46     ` Jeffrey R. Carter
@ 2018-03-11  0:38       ` Jere
  2018-03-11  9:57         ` Jeffrey R. Carter
  2018-03-12 23:30         ` Randy Brukardt
  0 siblings, 2 replies; 27+ messages in thread
From: Jere @ 2018-03-11  0:38 UTC (permalink / raw)


On Friday, March 9, 2018 at 11:46:03 AM UTC-5, Jeffrey R. Carter wrote:
> On 03/09/2018 01:36 AM, Jere wrote:
> > 
> > It generates the error "access-to-variable designates constant" because
> > the function takes a parameter of mode "in" while the iterator needs
> > a non-constant access to the variable.  I can't change the mode of the
> > function for other reasons.
> 
> OK, that's what I missed. I guess you could unchecked convert from 
> access-constant to access-all.
> 
My only concern with this is does the Ada language allow it portably?  I
know it works in GNAT, but what I couldn't find is if the RM allowed
for a constant variable to have a different internal representation than
a non constant version of the variable.  If that were the case, then I 
would be worried that doing an unchecked_conversion (or an
Address_To_Access_Conversion) could provide an erroneous result.

I've been dipping into the RM but haven't found what I am looking for yet.


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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-11  0:38       ` Jere
@ 2018-03-11  9:57         ` Jeffrey R. Carter
  2018-03-11 10:44           ` Dmitry A. Kazakov
  2018-03-11 14:31           ` Jere
  2018-03-12 23:30         ` Randy Brukardt
  1 sibling, 2 replies; 27+ messages in thread
From: Jeffrey R. Carter @ 2018-03-11  9:57 UTC (permalink / raw)


On 03/11/2018 01:38 AM, Jere wrote:
> On Friday, March 9, 2018 at 11:46:03 AM UTC-5, Jeffrey R. Carter wrote:
>>
>> OK, that's what I missed. I guess you could unchecked convert from
>> access-constant to access-all.
>>
> My only concern with this is does the Ada language allow it portably?  I
> know it works in GNAT, but what I couldn't find is if the RM allowed
> for a constant variable to have a different internal representation than
> a non constant version of the variable.  If that were the case, then I
> would be worried that doing an unchecked_conversion (or an
> Address_To_Access_Conversion) could provide an erroneous result.

Since your type is tagged, parameters are passed by reference, so your "in" 
parameter is a constant view of the variable. As such, it has the same 
representation as the full (non-constant) view of variable.

Nothing in the ARM puts any requirements on the representation of access types, 
so it's possible that access-constant and access-all could have different 
representations. The distinction between the two would seem to be a compile-time 
concept that would not be explicitly represented at run time. Given the general 
rule that compiler writers don't make things more difficult for themselves than 
they need to, it seems unlikely that the access values would have different 
representations, and unchecked converting between them should be OK. Input from 
compiler writers would be more valuable than my uneducated guessing, though.

Since tagged parameters are always aliased, address-to-access conversion should 
always be correct.

Why do you need this function?

-- 
Jeff Carter
"Sir Robin the not-quite-so-brave-as-Sir-Lancelot,
who had nearly fought the Dragon of Angnor,
who nearly stood up to the vicious Chicken of Bristol,
and who had personally wet himself at the
Battle of Badon Hill."
Monty Python & the Holy Grail
68


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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-11  9:57         ` Jeffrey R. Carter
@ 2018-03-11 10:44           ` Dmitry A. Kazakov
  2018-03-11 14:31           ` Jere
  1 sibling, 0 replies; 27+ messages in thread
From: Dmitry A. Kazakov @ 2018-03-11 10:44 UTC (permalink / raw)


On 2018-03-11 10:57, Jeffrey R. Carter wrote:

> Why do you need this function?

Iterators where there should be none, See the beginning of the thread.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-11  9:57         ` Jeffrey R. Carter
  2018-03-11 10:44           ` Dmitry A. Kazakov
@ 2018-03-11 14:31           ` Jere
  2018-03-11 15:49             ` Jeffrey R. Carter
  1 sibling, 1 reply; 27+ messages in thread
From: Jere @ 2018-03-11 14:31 UTC (permalink / raw)


On Sunday, March 11, 2018 at 5:57:47 AM UTC-4, Jeffrey R. Carter wrote:
> On 03/11/2018 01:38 AM, Jere wrote:
> > On Friday, March 9, 2018 at 11:46:03 AM UTC-5, Jeffrey R. Carter wrote:
> >>
> >> OK, that's what I missed. I guess you could unchecked convert from
> >> access-constant to access-all.
> >>
> > My only concern with this is does the Ada language allow it portably?  I
> > know it works in GNAT, but what I couldn't find is if the RM allowed
> > for a constant variable to have a different internal representation than
> > a non constant version of the variable.  If that were the case, then I
> > would be worried that doing an unchecked_conversion (or an
> > Address_To_Access_Conversion) could provide an erroneous result.
>
>    <SNIPPED>
> 
> Why do you need this function?
> 
It's iterator related.  In order to iterate through a container in all
contexts, the Default_Iterator function needs a parameter of mode "in".
In order to leverage the anti tamper functionality, the iterator needs
a non constant access to the container to be supplied when building
the iterator inside the Default_Iterator function (so it can modify
the tamper state of the container).  The GNAT body for the Vectors 
package has an example (I think it is a-convec.adb, just search for
"function iterate" and look for the one that returns an iterator).


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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-11 14:31           ` Jere
@ 2018-03-11 15:49             ` Jeffrey R. Carter
  2018-03-11 17:33               ` Jere
  0 siblings, 1 reply; 27+ messages in thread
From: Jeffrey R. Carter @ 2018-03-11 15:49 UTC (permalink / raw)


On 03/11/2018 03:31 PM, Jere wrote:
>>
> It's iterator related.  In order to iterate through a container in all
> contexts, the Default_Iterator function needs a parameter of mode "in".
> In order to leverage the anti tamper functionality, the iterator needs
> a non constant access to the container to be supplied when building
> the iterator inside the Default_Iterator function (so it can modify
> the tamper state of the container).  The GNAT body for the Vectors
> package has an example (I think it is a-convec.adb, just search for
> "function iterate" and look for the one that returns an iterator).

I doubt the intention of user-defined iteration was to require people to bypass 
the language checks, so I conclude that it's intended for the container 
parameter of the Default_Iterator function to have mode "in out". The definition 
of Default_Iterator doesn't restrict the parameter mode of the container 
parameter in any way, so "in out" should be accepted.

Presumably the Iterator functions for the standard containers have mode "in" for 
the containers because their bodies don't need to be portable and can use 
compiler-specific tricks, similar to the Generator parameter of the 
random-number functions from an earlier version of the language.

Or else user-defined iteration seems broken.

-- 
Jeff Carter
"Sir Robin the not-quite-so-brave-as-Sir-Lancelot,
who had nearly fought the Dragon of Angnor,
who nearly stood up to the vicious Chicken of Bristol,
and who had personally wet himself at the
Battle of Badon Hill."
Monty Python & the Holy Grail
68

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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-11 15:49             ` Jeffrey R. Carter
@ 2018-03-11 17:33               ` Jere
  2018-03-11 18:12                 ` Jeffrey R. Carter
  2018-03-11 18:27                 ` Niklas Holsti
  0 siblings, 2 replies; 27+ messages in thread
From: Jere @ 2018-03-11 17:33 UTC (permalink / raw)


On Sunday, March 11, 2018 at 11:49:28 AM UTC-4, Jeffrey R. Carter wrote:
> On 03/11/2018 03:31 PM, Jere wrote:
> >>
> > It's iterator related.  In order to iterate through a container in all
> > contexts, the Default_Iterator function needs a parameter of mode "in".
> > In order to leverage the anti tamper functionality, the iterator needs
> > a non constant access to the container to be supplied when building
> > the iterator inside the Default_Iterator function (so it can modify
> > the tamper state of the container).  The GNAT body for the Vectors
> > package has an example (I think it is a-convec.adb, just search for
> > "function iterate" and look for the one that returns an iterator).
> 
> I doubt the intention of user-defined iteration was to require people to bypass 
> the language checks, so I conclude that it's intended for the container 
> parameter of the Default_Iterator function to have mode "in out". The definition 
> of Default_Iterator doesn't restrict the parameter mode of the container 
> parameter in any way, so "in out" should be accepted.
> 
> Presumably the Iterator functions for the standard containers have mode "in" for 
> the containers because their bodies don't need to be portable and can use 
> compiler-specific tricks, similar to the Generator parameter of the 
> random-number functions from an earlier version of the language.
> 
> Or else user-defined iteration seems broken.

The problem I run into with this provided code base, is that it
often iterates over a constant view of the container.  In those cases,
Default_Iterator cannot have a mode of "in out" as you just get the error

"variable container expected"

If you refer back to my original question, I mentioned that I tried doing
this and got a slew of errors (like the one mentioned above).  I don't
have permission to completely rewrite things.  That's why I was trying to
tackle it from the Unrestricted_Access calls.  Changing those to 
Access_To_Address_Conversions implementations worked.  I just wasn't sure
it was kosher in portable Ada was all (hence my original question).

It's kind of an odd place to be.  You want the tamper checks to ensure
container safety/correctness, which potentially requires 
Default_Iterator to have mode "in out" but you also don't want to
restrict the Container to only be used in mutable situations.  If
you want to use a container in non mutable situations, you need 
Default_Iterator to have mode "in".  Without tamper checks, everything
can be mode "in" and happy.

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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-11 17:33               ` Jere
@ 2018-03-11 18:12                 ` Jeffrey R. Carter
  2018-03-11 19:53                   ` Jere
  2018-03-11 18:27                 ` Niklas Holsti
  1 sibling, 1 reply; 27+ messages in thread
From: Jeffrey R. Carter @ 2018-03-11 18:12 UTC (permalink / raw)


On 03/11/2018 06:33 PM, Jere wrote:
> 
> The problem I run into with this provided code base, is that it
> often iterates over a constant view of the container.  In those cases,
> Default_Iterator cannot have a mode of "in out" as you just get the error
> 
> "variable container expected"

I can't say I've ever done that.

> It's kind of an odd place to be.  You want the tamper checks to ensure
> container safety/correctness, which potentially requires
> Default_Iterator to have mode "in out" but you also don't want to
> restrict the Container to only be used in mutable situations.  If
> you want to use a container in non mutable situations, you need
> Default_Iterator to have mode "in".  Without tamper checks, everything
> can be mode "in" and happy.

So you want to bypass one kind of check in order to have another? Is it possible 
to tamper with a constant container?

I presume this code was written for an earlier version of the language, and now 
you want to bolt on this neat new feature of Ada 12. It seems its design and 
implementation are not compatible with user-defined iteration. It appears there 
are 2 clean solutions:

1. Do nothing. You don't need this form of iteration. The existing ways of 
iterating over the container work fine.

2. Revisit the design and modify the code so it's compatible with user-defined 
iteration.

Trying to use solution 1.5 is going to be messy.

-- 
Jeff Carter
"Sir Robin the not-quite-so-brave-as-Sir-Lancelot,
who had nearly fought the Dragon of Angnor,
who nearly stood up to the vicious Chicken of Bristol,
and who had personally wet himself at the
Battle of Badon Hill."
Monty Python & the Holy Grail
68

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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-11 17:33               ` Jere
  2018-03-11 18:12                 ` Jeffrey R. Carter
@ 2018-03-11 18:27                 ` Niklas Holsti
  2018-03-11 20:07                   ` Jere
  1 sibling, 1 reply; 27+ messages in thread
From: Niklas Holsti @ 2018-03-11 18:27 UTC (permalink / raw)


On 18-03-11 19:33 , Jere wrote:
> On Sunday, March 11, 2018 at 11:49:28 AM UTC-4, Jeffrey R. Carter wrote:
>> On 03/11/2018 03:31 PM, Jere wrote:
>>>>
>>> It's iterator related.  In order to iterate through a container in all
>>> contexts, the Default_Iterator function needs a parameter of mode "in".
>>> In order to leverage the anti tamper functionality, the iterator needs
>>> a non constant access to the container to be supplied when building
>>> the iterator inside the Default_Iterator function (so it can modify
>>> the tamper state of the container).  The GNAT body for the Vectors
>>> package has an example (I think it is a-convec.adb, just search for
>>> "function iterate" and look for the one that returns an iterator).
>>
>> I doubt the intention of user-defined iteration was to require people to bypass
>> the language checks, so I conclude that it's intended for the container
>> parameter of the Default_Iterator function to have mode "in out". The definition
>> of Default_Iterator doesn't restrict the parameter mode of the container
>> parameter in any way, so "in out" should be accepted.
>>
>> Presumably the Iterator functions for the standard containers have mode "in" for
>> the containers because their bodies don't need to be portable and can use
>> compiler-specific tricks, similar to the Generator parameter of the
>> random-number functions from an earlier version of the language.
>>
>> Or else user-defined iteration seems broken.
>
> The problem I run into with this provided code base, is that it
> often iterates over a constant view of the container.

One way to modify the semantic state of an object, through a constant 
view of the object, is to provide the object with a component that is an 
access to another object that contains the state you want to modify.

For example, to implement the tamper check, the container could have an 
"access Boolean" component where the Boolean is the flag that enables 
the tamper checks (or perhaps it should be a Natural, to handle nested 
iterations).

Or you could use the "Rosen trick", with a container component that is 
an access (variable view) to the container itself.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .


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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-11 18:12                 ` Jeffrey R. Carter
@ 2018-03-11 19:53                   ` Jere
  2018-03-12 16:28                     ` Jeffrey R. Carter
  0 siblings, 1 reply; 27+ messages in thread
From: Jere @ 2018-03-11 19:53 UTC (permalink / raw)


On Sunday, March 11, 2018 at 2:12:48 PM UTC-4, Jeffrey R. Carter wrote:
> On 03/11/2018 06:33 PM, Jere wrote:
> > It's kind of an odd place to be.  You want the tamper checks to ensure
> > container safety/correctness, which potentially requires
> > Default_Iterator to have mode "in out" but you also don't want to
> > restrict the Container to only be used in mutable situations.  If
> > you want to use a container in non mutable situations, you need
> > Default_Iterator to have mode "in".  Without tamper checks, everything
> > can be mode "in" and happy.
> 
> So you want to bypass one kind of check in order to have another? Is it possible 
> to tamper with a constant container?
> 
From a naive view where the client doesn't know the implementation of the
container, a client would expect to be able to do:

procedure Debug_Print(C : Container) is
begin
   for E of C loop
      Ada.Text_IO.Put_Line(Element'Image(E));
   end loop;
end Debug_Print;

Which is not possible with Default_Iterator that has mode "in out"
You get the earlier mentioned compiler error.  Note that here, no 
tamper check is needed and we are merely accessing a constant view 
of the container in a constant fashion (forgive the wrong terminology,
I don't know the right terminology here).

However, additionally, one might want to protect the client from this
situation:

procedure Nefarious(C : in out Container) is
begin
   for E of C loop
      if E = Some_Value then
         <do some stuff>
         C.Delete(E);  -- tamper check!
   end loop;
end Nefarious;

Here, someone is trying to delete an element during
iteration, which should be saved by tamper checks.

For reference, the Ada standard containers fulfill both of those 
scenarios.  The original dev team of this code base appears to
be mimicking the same methodology.

As a note, I'm not particularly thrilled about bypassing any checks.
The existing code already does it, and the request is to limit changes
to avoid large code overhauls.

> I presume this code was written for an earlier version of the language, and now 
> you want to bolt on this neat new feature of Ada 12. It seems its design and 
> implementation are not compatible with user-defined iteration. 

It's all pre-existing code.  I don't want to add anything.  The 
iteration was already there.  The owner asked to see if I could 
get rid of some GNAT specific extensions easily.
One was the use of Unrestricted_Access, which led me to the original
question.  They didn't want a major overhaul of the code.


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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-11 18:27                 ` Niklas Holsti
@ 2018-03-11 20:07                   ` Jere
  2018-03-12 23:35                     ` Randy Brukardt
  0 siblings, 1 reply; 27+ messages in thread
From: Jere @ 2018-03-11 20:07 UTC (permalink / raw)


On Sunday, March 11, 2018 at 2:27:08 PM UTC-4, Niklas Holsti wrote:
> On 18-03-11 19:33 , Jere wrote:
> > The problem I run into with this provided code base, is that it
> > often iterates over a constant view of the container.
> 
> One way to modify the semantic state of an object, through a constant 
> view of the object, is to provide the object with a component that is an 
> access to another object that contains the state you want to modify.
> 
> For example, to implement the tamper check, the container could have an 
> "access Boolean" component where the Boolean is the flag that enables 
> the tamper checks (or perhaps it should be a Natural, to handle nested 
> iterations).
> 
> Or you could use the "Rosen trick", with a container component that is 
> an access (variable view) to the container itself.

If I was allowed to redesign the code, I would definitely approach it
differently than the original author.  I'm not allowed to overhaul the 
existing code outside of very simple changes that don't impact any specs
or runtime behavior.  In this case, the specific request was can I
modify the code easily to avoid using the GNAT extension.  If not, 
then the owner would rather leave it as is.  

I was trying to verify that changing Container'Unrestricted_Acess to 
A2A.To_Pointer(Container'Address) was legit/legal/ok/etc.  I was a little
concerned it could invoke erroneous behavior (in a general language
sense) if the ARM allowed for different object representations for
constant vs non-constant variables.

At some point, I think both Dmitry and Jeff came under the assumption
that either I was writing this all from scratch or I was adding iteration
to something that didn't already have it (neither of which is true).  
I'm not even the original author.

On the Rosen Trick:  Can you do that for non-limited types?  Most of the
containers are not limited.


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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-11 19:53                   ` Jere
@ 2018-03-12 16:28                     ` Jeffrey R. Carter
  0 siblings, 0 replies; 27+ messages in thread
From: Jeffrey R. Carter @ 2018-03-12 16:28 UTC (permalink / raw)


On 03/11/2018 08:53 PM, Jere wrote:
> 
> procedure Debug_Print(C : Container) is
> begin
>     for E of C loop
>        Ada.Text_IO.Put_Line(Element'Image(E));
>     end loop;
> end Debug_Print;
> 
> procedure Nefarious(C : in out Container) is
> begin
>     for E of C loop
>        if E = Some_Value then
>           <do some stuff>
>           C.Delete(E);  -- tamper check!
>     end loop;
> end Nefarious;

If you can't do both with standard, checked programming, then user-defined 
iteration is broken.

> It's all pre-existing code.  I don't want to add anything.  The
> iteration was already there.  The owner asked to see if I could
> get rid of some GNAT specific extensions easily.
> One was the use of Unrestricted_Access, which led me to the original
> question.  They didn't want a major overhaul of the code.

Address-to-access conversions should be correct and portable, but 
'Unrestricted_Access is probably clearer.

-- 
Jeff Carter
"We'll make Rock Ridge think it's a chicken
that got caught in a tractor's nuts!"
Blazing Saddles
87

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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-11  0:38       ` Jere
  2018-03-11  9:57         ` Jeffrey R. Carter
@ 2018-03-12 23:30         ` Randy Brukardt
  2018-03-13  7:46           ` Niklas Holsti
  1 sibling, 1 reply; 27+ messages in thread
From: Randy Brukardt @ 2018-03-12 23:30 UTC (permalink / raw)


"Jere" <jhb.chat@gmail.com> wrote in message 
news:6792fcd7-a25a-417c-b45a-1a17b0168234@googlegroups.com...
> On Friday, March 9, 2018 at 11:46:03 AM UTC-5, Jeffrey R. Carter wrote:
>> On 03/09/2018 01:36 AM, Jere wrote:
>> >
>> > It generates the error "access-to-variable designates constant" because
>> > the function takes a parameter of mode "in" while the iterator needs
>> > a non-constant access to the variable.  I can't change the mode of the
>> > function for other reasons.
>>
>> OK, that's what I missed. I guess you could unchecked convert from
>> access-constant to access-all.
>>
> My only concern with this is does the Ada language allow it portably?

Jeff's answer is essentially correct: it ought to be OK for by-reference 
types -- in particular, see RM 3.3(13/3) which notes that controlled and 
immutably limited types are never really constant. For other types, however, 
the compiler is allowed to assume that a constant is not actually going to 
change, and that could mean ignoring any chances in subsequent code.

One easy way to get a rewritable reference of a controlled type is to save 
it in the Initialize routine (note that the argument of Initialize is "in 
out"). So you could have something like:

    type Container is tagged;
    type Acc_Container is access all Container;
    type Container is new Controlled with record
        Self : Acc_Container;
    end record;

    procedure Initialize (Obj : in out Container) is
    begin
         Obj.Self := Obj'Access;
    end Initialize;

And then you can use "Self" anytime you need to write the container object. 
Claw does this extensively (we didn't invent it for this reason, but we 
certainly used it this way).

If you have an immutably limited type, you can do this directly in the type 
declaration; it's known as the "Rosen technique" (or "trick" if you dislike 
it ;-). It's commonly used, and the reason we rewrote 3.3(13/3) for Ada 2012 
was to clarify that it was legitimate (it would be unfortunate for a 
widely-used technique that every Ada compiler needs to support to be 
formally erroneous).

                                                Randy.


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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-11 20:07                   ` Jere
@ 2018-03-12 23:35                     ` Randy Brukardt
  0 siblings, 0 replies; 27+ messages in thread
From: Randy Brukardt @ 2018-03-12 23:35 UTC (permalink / raw)


"Jere" <jhb.chat@gmail.com> wrote in message 
news:59ca25c1-ca05-4ec3-be4c-7b228ee57415@googlegroups.com...
...
> On the Rosen Trick:  Can you do that for non-limited types?  Most of the
> containers are not limited.

No, but you don't have to for controlled types. See my previous answer. If 
you need to do this for a bounded container, then you're out of luck. :-)

                                        Randy.


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

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-12 23:30         ` Randy Brukardt
@ 2018-03-13  7:46           ` Niklas Holsti
  0 siblings, 0 replies; 27+ messages in thread
From: Niklas Holsti @ 2018-03-13  7:46 UTC (permalink / raw)


On 18-03-13 01:30 , Randy Brukardt wrote:

> One easy way to get a rewritable reference of a controlled type is to save
> it in the Initialize routine (note that the argument of Initialize is "in
> out"). So you could have something like:
>
>     type Container is tagged;
>     type Acc_Container is access all Container;
>     type Container is new Controlled with record
>         Self : Acc_Container;
>     end record;
>
>     procedure Initialize (Obj : in out Container) is
>     begin
>          Obj.Self := Obj'Access;
>     end Initialize;
>
> And then you can use "Self" anytime you need to write the container object.

A note, just to remind myself and others: for a non-limited Container 
type this "Self" component must also be updated (in fact restored to its 
Initialized value) in the Adjust operation. Otherwise, if A and B are 
Container objects, after A := B the component A.Self would access B.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .


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

end of thread, other threads:[~2018-03-13  7:46 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-07 20:11 Ada Alternatives to Unrestricted_Access Jere
2018-03-07 20:38 ` Dmitry A. Kazakov
2018-03-07 22:29   ` Jere
2018-03-08  8:27     ` Dmitry A. Kazakov
2018-03-09  0:43       ` Jere
2018-03-09  0:52         ` Jere
2018-03-09  8:28           ` Dmitry A. Kazakov
2018-03-11  0:31             ` Jere
2018-03-08  3:18 ` gautier_niouzes
2018-03-09  0:41   ` Jere
2018-03-08 17:51 ` Jeffrey R. Carter
2018-03-09  0:36   ` Jere
2018-03-09 16:46     ` Jeffrey R. Carter
2018-03-11  0:38       ` Jere
2018-03-11  9:57         ` Jeffrey R. Carter
2018-03-11 10:44           ` Dmitry A. Kazakov
2018-03-11 14:31           ` Jere
2018-03-11 15:49             ` Jeffrey R. Carter
2018-03-11 17:33               ` Jere
2018-03-11 18:12                 ` Jeffrey R. Carter
2018-03-11 19:53                   ` Jere
2018-03-12 16:28                     ` Jeffrey R. Carter
2018-03-11 18:27                 ` Niklas Holsti
2018-03-11 20:07                   ` Jere
2018-03-12 23:35                     ` Randy Brukardt
2018-03-12 23:30         ` Randy Brukardt
2018-03-13  7:46           ` Niklas Holsti

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