comp.lang.ada
 help / color / mirror / Atom feed
* Visibility issue
@ 2020-09-11 10:37 Daniel
  2020-09-11 11:51 ` Maxim Reznik
                   ` (6 more replies)
  0 siblings, 7 replies; 32+ messages in thread
From: Daniel @ 2020-09-11 10:37 UTC (permalink / raw)


Hello,
I want to use a tagged type as a link to communicate users of a library, in the way to make one part visible to them and also to hide some content that is only needed for the implementing of the library.

Lets say i have the "Library" packages to expose things to users, and Implementing_Library packages to deal with the implementation:

package Library.Users is
   type User_type is tagged with private;
   procedure foo_public (S: User_Type);
private
   type User_Type is tagged with record
      hide_content_to_user : Natural;
   end record;
function Access_to_hide_content return User_type;
end Library.Users;

private with Library.Users;
package Internal_Library_Implementing is
-- Some internal public developer stuff
private
--Here I want to get access to User_Type hide content.
end Internal_Library_Implementing;

I've tried using "private with" but gnat says the next:
   move subprogram to the visible part (RM 3.9.3(10))
   private function with tagged result must override visible-part function

Compiler says Im forced to make all private User_type functions public.
So,  are there more ways to see the hided content of this tagged type without extending the type itself in a child package? I needed to see this content outside of Library package.



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

* Re: Visibility issue
  2020-09-11 10:37 Visibility issue Daniel
@ 2020-09-11 11:51 ` Maxim Reznik
  2020-09-11 20:11   ` Daniel
  2020-09-11 14:23 ` Jeffrey R. Carter
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 32+ messages in thread
From: Maxim Reznik @ 2020-09-11 11:51 UTC (permalink / raw)


You can try this way:

package Library.Users is 
   type User_type is tagged with private; 
...
end;
private package Library.Users.Implementation is 
...--  access User_Type internals
end;

In Matreshka[1] we use another approach. We have a separate hierarchy of package for internals (in Matreshka.XXX packages) and a public API in League.XXX packages. However, nothing stops the user from use internal packages there.

[1]: https://github.com/reznikmm/matreshka

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

* Re: Visibility issue
  2020-09-11 10:37 Visibility issue Daniel
  2020-09-11 11:51 ` Maxim Reznik
@ 2020-09-11 14:23 ` Jeffrey R. Carter
  2020-09-11 20:17   ` Daniel
  2020-09-11 21:05 ` Dmitry A. Kazakov
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 32+ messages in thread
From: Jeffrey R. Carter @ 2020-09-11 14:23 UTC (permalink / raw)


On 9/11/20 12:37 PM, Daniel wrote:
> 
> package Library.Users is
>     type User_type is tagged with private;
>     procedure foo_public (S: User_Type);
> private
>     type User_Type is tagged with record
>        hide_content_to_user : Natural;
>     end record;
> function Access_to_hide_content return User_type;
> end Library.Users;
> 
> private with Library.Users;
> package Internal_Library_Implementing is
> -- Some internal public developer stuff
> private
> --Here I want to get access to User_Type hide content.
> end Internal_Library_Implementing;
> 
> I've tried using "private with" but gnat says the next:
>     move subprogram to the visible part (RM 3.9.3(10))
>     private function with tagged result must override visible-part function
> 
> Compiler says Im forced to make all private User_type functions public.
> So,  are there more ways to see the hided content of this tagged type without extending the type itself in a child package? I needed to see this content outside of Library package.

The private part is only visible to the body and to child pkgs. So if you declared

private package Library.Users.Internal_Implementation is

then it will be able to see the private part of Library.Users. Because it's a 
private pkg, it cannot be used by clients.

-- 
Jeff Carter
"You couldn't catch clap in a brothel, silly English K...niggets."
Monty Python & the Holy Grail
19

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

* Re: Visibility issue
  2020-09-11 11:51 ` Maxim Reznik
@ 2020-09-11 20:11   ` Daniel
  0 siblings, 0 replies; 32+ messages in thread
From: Daniel @ 2020-09-11 20:11 UTC (permalink / raw)


El viernes, 11 de septiembre de 2020 a las 13:51:39 UTC+2, Maxim Reznik escribió:
> You can try this way:
> package Library.Users is 
> type User_type is tagged with private;
> ... 
> end; 
> private package Library.Users.Implementation is 
> ...-- access User_Type internals 
> end; 
> 
> In Matreshka[1] we use another approach. We have a separate hierarchy of package for internals (in Matreshka.XXX packages) and a public API in League.XXX packages. However, nothing stops the user from use internal packages there. 
> 
> [1]: https://github.com/reznikmm/matreshka

I think that what I was doing is really close to your example: having two separates hierarchy. One for API just for type conversions and user interface, and other package hierarchy for internal implementing.
Let me use the same names as your example.
I need to access from Internal Matreshka packages to the private part of API tagged type. If im obligated to put the implement details in the child package of API, i will need also all the dependencies located in the Matreshka.XXX. That will make a mess of dependencies.


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

* Re: Visibility issue
  2020-09-11 14:23 ` Jeffrey R. Carter
@ 2020-09-11 20:17   ` Daniel
  2020-09-11 22:36     ` Jeffrey R. Carter
  0 siblings, 1 reply; 32+ messages in thread
From: Daniel @ 2020-09-11 20:17 UTC (permalink / raw)


El viernes, 11 de septiembre de 2020 a las 16:23:26 UTC+2, Jeffrey R. Carter escribió:
> On 9/11/20 12:37 PM, Daniel wrote: 
> > 
> > package Library.Users is 
> > type User_type is tagged with private; 
> > procedure foo_public (S: User_Type); 
> > private 
> > type User_Type is tagged with record 
> > hide_content_to_user : Natural; 
> > end record; 
> > function Access_to_hide_content return User_type; 
> > end Library.Users; 
> > 
> > private with Library.Users; 
> > package Internal_Library_Implementing is 
> > -- Some internal public developer stuff 
> > private 
> > --Here I want to get access to User_Type hide content. 
> > end Internal_Library_Implementing; 
> > 
> > I've tried using "private with" but gnat says the next: 
> > move subprogram to the visible part (RM 3.9.3(10)) 
> > private function with tagged result must override visible-part function 
> > 
> > Compiler says Im forced to make all private User_type functions public. 
> > So, are there more ways to see the hided content of this tagged type without extending the type itself in a child package? I needed to see this content outside of Library package.
> The private part is only visible to the body and to child pkgs. So if you declared 
> 
> private package Library.Users.Internal_Implementation is 
> 
> then it will be able to see the private part of Library.Users. Because it's a 
> private pkg, it cannot be used by clients. 
> 
> -- 
> Jeff Carter 
> "You couldn't catch clap in a brothel, silly English K...niggets." 
> Monty Python & the Holy Grail 
> 19

I was trying to separate the code in two hierarchies packages, one package for an API and other package for internal implementation.
IT's difficult to put the implementing details on the API "fake child" because I will need a lot of dependencies from Internal packages hierarchy.

It could be possible to use other solution different that put implementing details on API packages?


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

* Re: Visibility issue
  2020-09-11 10:37 Visibility issue Daniel
  2020-09-11 11:51 ` Maxim Reznik
  2020-09-11 14:23 ` Jeffrey R. Carter
@ 2020-09-11 21:05 ` Dmitry A. Kazakov
  2020-09-14 11:33   ` Daniel
  2020-09-14 16:18 ` Simon Wright
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 32+ messages in thread
From: Dmitry A. Kazakov @ 2020-09-11 21:05 UTC (permalink / raw)


On 11/09/2020 12:37, Daniel wrote:

> I want to use a tagged type as a link to communicate users of a library, in the way to make one part visible to them and also to hide some content that is only needed for the implementing of the library.
> 
> Lets say i have the "Library" packages to expose things to users, and Implementing_Library packages to deal with the implementation:
> 
> package Library.Users is
>     type User_type is tagged with private;
>     procedure foo_public (S: User_Type);
> private
>     type User_Type is tagged with record
>        hide_content_to_user : Natural;
>     end record;
> function Access_to_hide_content return User_type;

Why is this a primitive operation? I would consider rather

    function Access_to_hide_content return User_type'Class;

In presence of potential overriding things like these are usually 
class-wide.

> So,  are there more ways to see the hided content of this tagged type without extending the type itself in a child package? I needed to see this content outside of Library package.

You can also use aggregation:

    type User_type is tagged with private;
private
    type User_type is tagged with record
       Implementation : Private_Stuff;
    end record;

Private_Stuff may have its own hierarchy. This pattern works well with 
limited types. You want the interface being non-limited, but the 
implementation of limited in order to control/prevent excessive copying 
and support in-place updates. So you make the interface a holder or a 
smart pointer to the reference-counted implementation.

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

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

* Re: Visibility issue
  2020-09-11 20:17   ` Daniel
@ 2020-09-11 22:36     ` Jeffrey R. Carter
  2020-09-14 10:47       ` Daniel
  0 siblings, 1 reply; 32+ messages in thread
From: Jeffrey R. Carter @ 2020-09-11 22:36 UTC (permalink / raw)


On 9/11/20 10:17 PM, Daniel wrote:
> 
> I was trying to separate the code in two hierarchies packages, one package for an API and other package for internal implementation.
> IT's difficult to put the implementing details on the API "fake child" because I will need a lot of dependencies from Internal packages hierarchy.
> 
> It could be possible to use other solution different that put implementing details on API packages?

For the visibility you say you want, you have to have your implementation 
hierarchy be a child hierarchy of your interface hierarchy. It's undoubtedly 
possible to design such a system so your implementation hierarchy does not need 
to be a child hierarchy, but where things are declared and what is visible where 
would be different.

-- 
Jeff Carter
"You couldn't catch clap in a brothel, silly English K...niggets."
Monty Python & the Holy Grail
19

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

* Re: Visibility issue
  2020-09-11 22:36     ` Jeffrey R. Carter
@ 2020-09-14 10:47       ` Daniel
  2020-09-14 16:10         ` Jeffrey R. Carter
  0 siblings, 1 reply; 32+ messages in thread
From: Daniel @ 2020-09-14 10:47 UTC (permalink / raw)



> hierarchy be a child hierarchy of your interface hierarchy. It's undoubtedly 
> possible to design such a system so your implementation hierarchy does not need 
> to be a child hierarchy, but where things are declared and what is visible where 
> would be different.
Thank you for your answer. ¿ Do you know some idea or design pattern to achieve this?
I didn't write it in the example for simplicity, but the user have to set a callback function.
This callback function is triggered in the internal implementation hierarchy packages. Let me show you. the questions are inside comments:

--- API SIDE: -----
package API.Callbacks
   type Handle is tagged private
   type pointer_to_Procedure is access procedure (Self : API.CAllbacks.Handle );
   procedure Set_Callback (Self: in out API_HandleCallBack; cp: CallbackProcedure  );

private   
   type Handle is tagged record
      Hidden : Natural;
   end record;
  procedure Hidden_constructor (S: in out Handle'Class ; Hidden_content :Natural);
---------------
----- IMPLEMENTING SIDE: --------
with API.Callbacks;
package body Internal.TASKS_Callbacks is

task body Caller is

 MyHandle : API.Handle;
 cp: CallbackProcedure := Get_from_pool_of_callbacks;
begin
   --Cannot access to private part for API.Handle from here :(
   -- Just want to set a hidden content from here using Hidden_Constructor and later call:
   cp (MyHandle);
end Caller;

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

* Re: Visibility issue
  2020-09-11 21:05 ` Dmitry A. Kazakov
@ 2020-09-14 11:33   ` Daniel
  2020-09-14 14:42     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 32+ messages in thread
From: Daniel @ 2020-09-14 11:33 UTC (permalink / raw)


Thank you for your answer Dmitry. Let me focus and change my example to easier go to the problem. I will write some question to your answer at the end of the example.

I didn't write it in the example for simplicity, but the user has to set a callback function.
This callback function is triggered in the internal implementation hierarchy packages. Let me show you the code within questions inside comments:

--- API SIDE: -----
package API.Callbacks
   type Handle is tagged private
   type pointer_to_Procedure is access procedure (Self : API.CAllbacks.Handle );
   procedure Set_Callback (Self: in out API_HandleCallBack; cp: CallbackProcedure  );
private
   type Handle is tagged record
      Hidden : Natural;
   end record;
  procedure Hidden_constructor (S: in out Handle'Class ; Hidden_content :Natural);
---------------
----- IMPLEMENTING SIDE: --------
private with API.Callbacks;
package body Internal.TASKS_Callbacks is

task body Caller is

 MyHandle : API.Handle;
 cp: CallbackProcedure := Get_from_pool_of_callbacks;
begin
  Hidden_Constructor (MyHandle, 6);
   --Cannot access to private part for API.Handle from here :(
  -- compiler says that Hidden_Constructor is not a visible entity of" Callbacks"
  -- I just wanted to build it to later call to the procedure:
   cp (MyHandle);
end Caller;

> Why is this a primitive operation? I would consider rather 
> 
> function Access_to_hide_content return User_type'Class; 
> 
> In presence of potential overriding things like these are usually 
> class-wide.
Using the updated example I've tried to use an Hidden_constructor using class-wide but compiler says
>"Hidden_Constructor" is not a visible entity of API.Callbacks.

.
> You can also use aggregation:
> type User_type is tagged with private;
> private 
> type User_type is tagged with record 
> Implementation : Private_Stuff; 
> end record; 
> 
> Private_Stuff may have its own hierarchy. This pattern works well with 
> limited types. You want the interface being non-limited, but the 
> implementation of limited in order to control/prevent excessive copying 
> and support in-place updates. So you make the interface a holder or a 
> smart pointer to the reference-counted implementation. 

Thank you for the idea, but I don't know if its really possible for the callback action I need to "call".
Lets say i extend Handle outside of API package hierarchy:

private with API.Callbacks;
package Internal.TASKS_Callbacks is
   type Handle_child is new API.Calbacks.Handle with null record;
  procedure Hidden_constructor (S: in out Handle_child; Hidden_content :Natural);
-------
package body Internal.TASKS_Callbacks is

task body Caller is

 MyHandle : Handle_child;
 mycall: CallbackProcedure := Get_from_pool_of_callbacks;
begin
  Hidden_Constructor (MyHandle, 6);
-- But now i need to trigger the callback procedure and that procedure is defined using Handle type, not the child Handle_child
-- how can i call the original callback procedure???
-- if I do the next 
mycall (MyHandle); --it raises that expect the father, not the child:

end task;

As you see.. how can i call from here the User callback procedure?


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

* Re: Visibility issue
  2020-09-14 11:33   ` Daniel
@ 2020-09-14 14:42     ` Dmitry A. Kazakov
  2020-09-15 19:35       ` Daniel
  0 siblings, 1 reply; 32+ messages in thread
From: Dmitry A. Kazakov @ 2020-09-14 14:42 UTC (permalink / raw)


On 14/09/2020 13:33, Daniel wrote:
> Thank you for your answer Dmitry. Let me focus and change my example to easier go to the problem. I will write some question to your answer at the end of the example.
> 
> I didn't write it in the example for simplicity, but the user has to set a callback function.
> This callback function is triggered in the internal implementation hierarchy packages. Let me show you the code within questions inside comments:
> 
> --- API SIDE: -----
> package API.Callbacks
>     type Handle is tagged private
>     type pointer_to_Procedure is access procedure (Self : API.CAllbacks.Handle );
>     procedure Set_Callback (Self: in out API_HandleCallBack; cp: CallbackProcedure  );
> private
>     type Handle is tagged record
>        Hidden : Natural;
>     end record;
>    procedure Hidden_constructor (S: in out Handle'Class ; Hidden_content :Natural);

You need a constructing function for your Handle

    package API.Callbacks
       type Handle is tagged private;
       function Create (Parameter : Natural) return Handle;

or else a factory object:

    type Factory is new
       abstract Ada.Finalization.Limited_Controlled with null record;
    function Create (Creator : in out Factory; ...)
       return Handle'Class is abstract;

> task body Caller is
> 
>   MyHandle : API.Handle;
>   cp: CallbackProcedure := Get_from_pool_of_callbacks;
> begin
>    Hidden_Constructor (MyHandle, 6);
>     --Cannot access to private part for API.Handle from here :(
>    -- compiler says that Hidden_Constructor is not a visible entity of" Callbacks"
>    -- I just wanted to build it to later call to the procedure:
>     cp (MyHandle);
> end Caller;

    task body Caller is
       My_Handle : Handle := Create (6);
    ...

As for callbacks, in Ada you could have a tagged object like 
Event_Handler. The callback will be a primitive operation of Event_Handler:

    type Event_Handler is
       abstract Ada.Finalization.Limited_Controlled with null record;
    procedure On_Event
              (  Handler : in out Event_Handler;
                 Object  : in out Handle
              )  is abstract;
    procedure Register
              (  Object  : in out Handle;
                 Handler : in out Event_Handler'Class
              );

The advantage: you derive from Event_Handler and can add whatever data 
you want.

Another pattern is a generic package or a generic subroutine. It is 
useful when you want to pass a closure, e.g. local variables to the 
callback without much fuss. E.g. a one-shot callbacks, visitors could be 
done this way.

    generic
       with function Visitor (Object : in out Handle'Class)
         return Boolean;
    procedure For_Each (Object : in out Handle'Class);

Both are capable to nicely breach privacy if you put them into child 
packages. Both do not suffer the accessibility level issues named access 
to subprogram types have.

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

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

* Re: Visibility issue
  2020-09-14 10:47       ` Daniel
@ 2020-09-14 16:10         ` Jeffrey R. Carter
  2020-09-15 19:11           ` Daniel
  0 siblings, 1 reply; 32+ messages in thread
From: Jeffrey R. Carter @ 2020-09-14 16:10 UTC (permalink / raw)


On 9/14/20 12:47 PM, Daniel wrote:
> 
> Thank you for your answer. ¿ Do you know some idea or design pattern to achieve this?
> I didn't write it in the example for simplicity, but the user have to set a callback function.
> This callback function is triggered in the internal implementation hierarchy packages. Let me show you. the questions are inside comments:

I'm not a big fan of callbacks or named access-to-subprogram types. A generic 
formal subprogram or an anonymous access-to-subprogram parameter is usually better.

I'm still not clear what problem you're trying to solve. Designs are derived 
from problem statements, not from failed designs

-- 
Jeff Carter
"Since I strongly believe that overpopulation is by
far the greatest problem in the world, this [Soylent
Green] would be my only message movie."
Charleton Heston
123

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

* Re: Visibility issue
  2020-09-11 10:37 Visibility issue Daniel
                   ` (2 preceding siblings ...)
  2020-09-11 21:05 ` Dmitry A. Kazakov
@ 2020-09-14 16:18 ` Simon Wright
  2020-09-17 15:58 ` Jere
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 32+ messages in thread
From: Simon Wright @ 2020-09-14 16:18 UTC (permalink / raw)


Daniel <danielnorberto@gmail.com> writes:

> I want to use a tagged type as a link to communicate users of a library

Why does this user-visible construct need to involve a tagged type? Use
tagged types as required internally, but all you seem to be doing is
making life difficult for yourself.

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

* Re: Visibility issue
  2020-09-14 16:10         ` Jeffrey R. Carter
@ 2020-09-15 19:11           ` Daniel
  2020-09-15 20:03             ` Jeffrey R. Carter
  0 siblings, 1 reply; 32+ messages in thread
From: Daniel @ 2020-09-15 19:11 UTC (permalink / raw)



> I'm still not clear what problem you're trying to solve. Designs are derived 
> from problem statements, not from failed designs 
I have the next requirements:
- I need to pack all calls from users in just one Package API Hierarchy.
- The details and complexity of the implementation need to be outside of this API hierarchy as much as possible.
-I need to use tagged types as much as possible for the calls from users to API package. (I'm not a big fan of this also but its a requirement)
-This API tagged types needs to connect the API Side with the implementation packages.
-The user needs to set a limited number of callback procedure with this flavor: "Procedure (S : in out Tagged_APi_Type)"
-The Implementation package needs to trigger the procedure defined in the API. (Here comes to problems):
-->The implementation package needs to manipulate some hide part of the Tagged_API_Type while is triggered
------>Here comes the problem. From the implementing  package  is not possible to see the private part of the API package.

The only solution I have for now is to make public some functions in the API to be used from the implementing packages and try to advise the users to don't use them.

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

* Re: Visibility issue
  2020-09-14 14:42     ` Dmitry A. Kazakov
@ 2020-09-15 19:35       ` Daniel
  2020-09-16  7:14         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 32+ messages in thread
From: Daniel @ 2020-09-15 19:35 UTC (permalink / raw)


El lunes, 14 de septiembre de 2020 a las 16:42:26 UTC+2, Dmitry A. Kazakov escribió:
> task body Caller is 
> My_Handle : Handle := Create (6); 
Dmitry, let me paste my answer i give to Jeff as an introduction to explain better the problem. First of all, I want to thank you to point me to different options. I will think about to refactoring everything i have or even build from scratch if I'm not able to build from what i already have.

For the requirements, It's not a problem to have a public constructor for the handle, in fact, i will need one for users. The real problem is to have constructors or function that i need to be visible from implementing packages and at the same time NOT visible from users that only are allowed to do a "with API.XXX"

I have the next requirements:
- I need to pack all calls from users in just one Package API Hierarchy.
- The details and complexity of the implementation needs to be outside of this API hierarchy as much as possible.
-I need to use tagged types as much as possible for the calls from users to API package. (I'm not a big fan of this also but its a requirement)
-This API tagged types needs to connect the API Side with the implementation packages.
-The user needs to set a limited number of callback procedure with this flavor: "Procedure (S : in out Tagged_APi_Type)"
-The Implementation package needs to trigger the procedure defined in the API. (Here comes to problems):
-->The implementation package needs to manipulate some hide part of the Tagged_API_Type when is triggered
------>Here comes the problem. From the implementing  package  is not possible to see the private part of the API package. I think because visibility is not related to type, is related to package where package exists.

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

* Re: Visibility issue
  2020-09-15 19:11           ` Daniel
@ 2020-09-15 20:03             ` Jeffrey R. Carter
  0 siblings, 0 replies; 32+ messages in thread
From: Jeffrey R. Carter @ 2020-09-15 20:03 UTC (permalink / raw)


On 9/15/20 9:11 PM, Daniel wrote:
> 
>> I'm still not clear what problem you're trying to solve. Designs are derived
>> from problem statements, not from failed designs
> I have the next requirements:
> - I need to pack all calls from users in just one Package API Hierarchy.
> - The details and complexity of the implementation need to be outside of this API hierarchy as much as possible.
> -I need to use tagged types as much as possible for the calls from users to API package. (I'm not a big fan of this also but its a requirement)
> -This API tagged types needs to connect the API Side with the implementation packages.
> -The user needs to set a limited number of callback procedure with this flavor: "Procedure (S : in out Tagged_APi_Type)"
> -The Implementation package needs to trigger the procedure defined in the API. (Here comes to problems):
> -->The implementation package needs to manipulate some hide part of the Tagged_API_Type while is triggered
> ------>Here comes the problem. From the implementing  package  is not possible to see the private part of the API package.
> 
> The only solution I have for now is to make public some functions in the API to be used from the implementing packages and try to advise the users to don't use them.

These are mostly restrictions on the implementation, not a problem statement. It 
seems you have requirements that it must use an impossible implementation.

-- 
Jeff Carter
"That was the most fun I've ever had without laughing."
Annie Hall
43
, not a

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

* Re: Visibility issue
  2020-09-15 19:35       ` Daniel
@ 2020-09-16  7:14         ` Dmitry A. Kazakov
  2020-09-16 10:23           ` Daniel
  0 siblings, 1 reply; 32+ messages in thread
From: Dmitry A. Kazakov @ 2020-09-16  7:14 UTC (permalink / raw)


On 15/09/2020 21:35, Daniel wrote:
> El lunes, 14 de septiembre de 2020 a las 16:42:26 UTC+2, Dmitry A. Kazakov escribió:
>> task body Caller is
>> My_Handle : Handle := Create (6);
> Dmitry, let me paste my answer i give to Jeff as an introduction to explain better the problem. First of all, I want to thank you to point me to different options. I will think about to refactoring everything i have or even build from scratch if I'm not able to build from what i already have.
> 
> For the requirements, It's not a problem to have a public constructor for the handle, in fact, i will need one for users. The real problem is to have constructors or function that i need to be visible from implementing packages and at the same time NOT visible from users that only are allowed to do a "with API.XXX"
> 
> I have the next requirements:
> - I need to pack all calls from users in just one Package API Hierarchy.
> - The details and complexity of the implementation needs to be outside of this API hierarchy as much as possible.
> -I need to use tagged types as much as possible for the calls from users to API package. (I'm not a big fan of this also but its a requirement)
> -This API tagged types needs to connect the API Side with the implementation packages.
> -The user needs to set a limited number of callback procedure with this flavor: "Procedure (S : in out Tagged_APi_Type)"
> -The Implementation package needs to trigger the procedure defined in the API. (Here comes to problems):
> -->The implementation package needs to manipulate some hide part of the Tagged_API_Type when is triggered
> ------>Here comes the problem. From the implementing  package  is not possible to see the private part of the API package. I think because visibility is not related to type, is related to package where package exists.

That is OK, but the hidden part need to be constructed in some way. Your 
requirements are silent about how. There exist only two possibilities, 
it is either generated internally or else provided by the client 
externally in some form, e.g. as parameters for the constructing function.

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

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

* Re: Visibility issue
  2020-09-16  7:14         ` Dmitry A. Kazakov
@ 2020-09-16 10:23           ` Daniel
  2020-09-16 10:58             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 32+ messages in thread
From: Daniel @ 2020-09-16 10:23 UTC (permalink / raw)


El miércoles, 16 de septiembre de 2020 a las 9:14:23 UTC+2, Dmitry A. Kazakov escribió:

> That is OK, but the hidden part needs to be constructed in some way. Your 
> requirements are silent about how. There exist only two possibilities, 
> it is either generated internally or else provided by the client 
> externally in some form, e.g. as parameters for the constructing function.
The Requirements are not constraining how to construct the API handle in both sides (Client, API and Internal). Im lucky with that. :)
Let's try to set and construct all hidden part details from Internal side, not from user side. I will add Just a public Registering type because it will be a limited pool of callbacks and users needs to Identify them.

What needs to know the user?
  -the implementation of the callback procedure it self
  -A number that identify this procedure (they are constrained to lets say just 12 procedures)

What needs to know and access the Internal package side?
   - A hidden part of Handle_type with dirty details about buffer pointers that needs to be set before triggering the procedure.
  - The callback procedure from a pool implemented in the same Internal package hierarchy that previously set the user.

Let me expose a simplification using the 3 parts: Client, API, Implementing.

-- USER SIDE: ---
procedure mycallback6 (S: in out Handle) is
begin
---call to public Handle functions
   ada.text_io.Put_Line(S.public_for_users);
end mycallback6;

procedure Initialize is
MyUserCallbackRegister : Register_type := (mycallback'Access , 6);
begin
null;
end Initialize;

-- API SIDE: ---------
package API.Callbacks
--Manage the callback:
type Handle is tagged private
type pointer_to_Procedure is access procedure (Self : API.CAllbacks.Handle );
function public_for_users(S: in out Handle) return string;
--Manage registering the callback
type Register_type is private;
function Register_Callback ( cp: CallbackProcedure , ID: Natural ) return Register_type ;
private
type Handle is tagged record
Usefull_for_Implementing_side : Pointer_To_buffer_type;
Register : Register_type; 
end record;
end package API.Callbacks;
type Register_type is Natural;

with Internal.Pool;
package body API.Callbacks is
function Register_Callback ( cp: CallbackProcedure , ID: Natural ) return Register_type  is
begin
   Internal.CallbacksPool.Set( cp, ID);
  return Register_type'(ID);
end Register_Callback;

----- IMPLEMENTING SIDE: --------
with API.Callbacks;
with Buffer_Stuff;
package body Internal.CallbacksPool is

task body InteranalCaller6 is
MyInternalHandle : API.Handle;
callbackprocedure: API.CallbackProcedure := Get_from_pool_of_callbacks (6);
begin
-- I need to set here the private part of MyInternalHandle defined in API.Handle before triggering and I Can't. :(
-- If I want to set this private part with a function, the only way is to make it public and accessible for users too.
 MyInternalHandle := ????
--Later I trigger:
 callbackprocedure (MyInternalHandle);
end InteranalCaller6 ;

end Internal.CallbacksPool;
-----------------------------------

So, here comes my options:
-- Set MyInternalHandle with a public function visible to users in API and tryng to explain them with education that they can't use it.
-- Implement the Internal details in API package hierarchy extending API.Handle
-- Saying to who give me this requirements I can't do it using Ada (and probably any other language)
-- Some other magic idea to implement this totally different :)

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

* Re: Visibility issue
  2020-09-16 10:23           ` Daniel
@ 2020-09-16 10:58             ` Dmitry A. Kazakov
  2020-09-16 14:35               ` Daniel
  0 siblings, 1 reply; 32+ messages in thread
From: Dmitry A. Kazakov @ 2020-09-16 10:58 UTC (permalink / raw)


On 16/09/2020 12:23, Daniel wrote:
> El miércoles, 16 de septiembre de 2020 a las 9:14:23 UTC+2, Dmitry A. Kazakov escribió:

> Let's try to set and construct all hidden part details from Internal side, not from user side.
[...]

Assuming "internal side" means "implementation side", this is in clear 
contradiction with the code you posted. Your package Internal is 
implementation and thus must be able to access whatever implementation 
details it needs.

Otherwise the API must provide means of construction. [Must be done 
anyway in order to ensure the contract of Handle, provided default 
initialization does not do that.]

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

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

* Re: Visibility issue
  2020-09-16 10:58             ` Dmitry A. Kazakov
@ 2020-09-16 14:35               ` Daniel
  2020-09-16 14:49                 ` Jeffrey R. Carter
  2020-09-16 15:05                 ` Dmitry A. Kazakov
  0 siblings, 2 replies; 32+ messages in thread
From: Daniel @ 2020-09-16 14:35 UTC (permalink / raw)


El miércoles, 16 de septiembre de 2020 a las 12:58:58 UTC+2, Dmitry A. Kazakov escribió:
> On 16/09/2020 12:23, Daniel wrote: 
> > El miércoles, 16 de septiembre de 2020 a las 9:14:23 UTC+2, Dmitry A. Kazakov escribió: 
> 
> > Let's try to set and construct all hidden part details from Internal side, not from user side.
> [...] 
> 
> Assuming "internal side" means "implementation side", this is in clear 
> contradiction with the code you posted. Your package Internal is 
> implementation and thus must be able to access whatever implementation 
> details it needs. 
> 
> Otherwise the API must provide means of construction. [Must be done 
> anyway in order to ensure the contract of Handle, provided default 
> initialization does not do that.]

Then, I assume there is not a clear solution in Ada due to my imposed requirements (I'm not sure if it's possible with another language also)
So if the "Implementation side" needs all details, I only think in two options :
1.- Put the details of implementation in a children package in the API hierarchy, and try to explain users to don't "with it". I can try to make it really empty in the public part of the children package and only put what its needed for the implementation.
2.- Take out the details from "API hierarchy packages" to the "Implementation package hierarchy" and make visible everything I need in the "API side", and try also to explain users to don't use them.

I think will go for the first option. If you think there is another solution I will be glad to hear that.
In any case, thank you for the help! I'm Learning every day with the help of this group.

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

* Re: Visibility issue
  2020-09-16 14:35               ` Daniel
@ 2020-09-16 14:49                 ` Jeffrey R. Carter
  2020-09-16 15:05                 ` Dmitry A. Kazakov
  1 sibling, 0 replies; 32+ messages in thread
From: Jeffrey R. Carter @ 2020-09-16 14:49 UTC (permalink / raw)


On 9/16/20 4:35 PM, Daniel wrote:
> 
> Then, I assume there is not a clear solution in Ada due to my imposed requirements (I'm not sure if it's possible with another language also)
> So if the "Implementation side" needs all details, I only think in two options :
> 1.- Put the details of implementation in a children package in the API hierarchy, and try to explain users to don't "with it". I can try to make it really empty in the public part of the children package and only put what its needed for the implementation.
> 2.- Take out the details from "API hierarchy packages" to the "Implementation package hierarchy" and make visible everything I need in the "API side", and try also to explain users to don't use them.

3. You recognize that you have things that are common to both hierarchies, and 
put them somewhere that both can access.

-- 
Jeff Carter
"IMHO, Interfaces are worthless."
Randy Brukardt
117

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

* Re: Visibility issue
  2020-09-16 14:35               ` Daniel
  2020-09-16 14:49                 ` Jeffrey R. Carter
@ 2020-09-16 15:05                 ` Dmitry A. Kazakov
  2020-09-16 20:09                   ` Daniel
  1 sibling, 1 reply; 32+ messages in thread
From: Dmitry A. Kazakov @ 2020-09-16 15:05 UTC (permalink / raw)


On 16/09/2020 16:35, Daniel wrote:
> El miércoles, 16 de septiembre de 2020 a las 12:58:58 UTC+2, Dmitry A. Kazakov escribió:
>> On 16/09/2020 12:23, Daniel wrote:
>>> El miércoles, 16 de septiembre de 2020 a las 9:14:23 UTC+2, Dmitry A. Kazakov escribió:
>>
>>> Let's try to set and construct all hidden part details from Internal side, not from user side.
>> [...]
>>
>> Assuming "internal side" means "implementation side", this is in clear
>> contradiction with the code you posted. Your package Internal is
>> implementation and thus must be able to access whatever implementation
>> details it needs.
>>
>> Otherwise the API must provide means of construction. [Must be done
>> anyway in order to ensure the contract of Handle, provided default
>> initialization does not do that.]
> 
> Then, I assume there is not a clear solution in Ada due to my imposed requirements

Why? It is not in requirements, it is solely your design.

I see no reason why the package Internal.CallbacksPool must be limited 
to the public API. But I also see no reason why public API does not 
provide means to construct fully functional handles.

> So if the "Implementation side" needs all details,

Implementation holds all details, per definition of implementation.

> I only think in two options :
> 1.- Put the details of implementation in a children package in the API hierarchy, and try to explain users to don't "with it". I can try to make it really empty in the public part of the children package and only put what its needed for the implementation.

1. Children packages can be private. You cannot with them from outside.

2. Nothing forces you to put anything into the public part of a public 
child package. With-ing it would expose nothing.

3. Packages can be nested and put into bodies of other packages. These 
will not exist as library packages for the user.

4. Packages can have separate bodies if become too large. These bodies 
are all private.

There are lots of ways to make things private in Ada.

[There are a few cases when privacy does not work in Ada, but none of 
those are related to your problem]

> 2.- Take out the details from "API hierarchy packages" to the "Implementation package hierarchy" and make visible everything I need in the "API side", and try also to explain users to don't use them.

There is absolutely no need doing this.

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

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

* Re: Visibility issue
  2020-09-16 15:05                 ` Dmitry A. Kazakov
@ 2020-09-16 20:09                   ` Daniel
  2020-09-16 21:48                     ` Simon Wright
  0 siblings, 1 reply; 32+ messages in thread
From: Daniel @ 2020-09-16 20:09 UTC (permalink / raw)


El miércoles, 16 de septiembre de 2020 a las 17:05:07 UTC+2, Dmitry A. Kazakov escribió:
> On 16/09/2020 16:35, Daniel wrote: 
> > El miércoles, 16 de septiembre de 2020 a las 12:58:58 UTC+2, Dmitry A. Kazakov escribió: 
> >> On 16/09/2020 12:23, Daniel wrote: 
> >>> El miércoles, 16 de septiembre de 2020 a las 9:14:23 UTC+2, Dmitry A. Kazakov escribió: 
> >> 
> >>> Let's try to set and construct all hidden part details from Internal side, not from user side. 
> >> [...] 
> >> 
> >> Assuming "internal side" means "implementation side", this is in clear 
> >> contradiction with the code you posted. Your package Internal is 
> >> implementation and thus must be able to access whatever implementation 
> >> details it needs. 
> >> 
> >> Otherwise the API must provide means of construction. [Must be done 
> >> anyway in order to ensure the contract of Handle, provided default 
> >> initialization does not do that.] 
> > 
> > Then, I assume there is not a clear solution in Ada due to my imposed requirements
> Why? It is not in requirements, it is solely your design. 
> 
> I see no reason why the package Internal.CallbacksPool must be limited 
> to the public API. But I also see no reason why public API does not 
> provide means to construct fully functional handles.
> > So if the "Implementation side" needs all details,
> Implementation holds all details, per definition of implementation.
> > I only think in two options : 
> > 1.- Put the details of implementation in a children package in the API hierarchy, and try to explain users to don't "with it". I can try to make it really empty in the public part of the children package and only put what its needed for the implementation.
> 1. Children packages can be private. You cannot with them from outside. 
> 
> 2. Nothing forces you to put anything into the public part of a public 
> child package. With-ing it would expose nothing. 
> 
> 3. Packages can be nested and put into bodies of other packages. These 
> will not exist as library packages for the user. 
> 
> 4. Packages can have separate bodies if become too large. These bodies 
> are all private. 
> 
> There are lots of ways to make things private in Ada. 
> 
> [There are a few cases when privacy does not work in Ada, but none of 
> those are related to your problem]
> > 2.- Take out the details from "API hierarchy packages" to the "Implementation package hierarchy" and make visible everything I need in the "API side", and try also to explain users to don't use them.
> There is absolutely no need doing this.
> -- 
> Regards, 
> Dmitry A. Kazakov 
> http://www.dmitry-kazakov.de

OK, I think maybe I'm not explaining the problem precisely. Before going for the first option I'm curious to explore and to learn how can be done using the second option.

Let me start from scratch.
I want to make a design that fits the next requirements/limitations:

-There will be just one API package hierarchy that users can "with it"
-This API hierarchy will define a callback procedure type with a tagged type as an argument
-This tagged type argument of the callback procedure template will be defined in  API hierarchy including a set of procedures in order to access and convert information to users.

-There will be one or more internal packages not visible to users where information is created. Preferably not in API hierarchy
-The information will be passed to users with the callback procedure they already wrote and they already set using API.
- Internal information data types must be decoupled from API data types.
- Usually, information that is generated internally is bigger than the user needs to know, so API tagged type argument of the callback procedure needs to convert it

¿With these requirements/limitations, which design approach you think is better to start the design?

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

* Re: Visibility issue
  2020-09-16 20:09                   ` Daniel
@ 2020-09-16 21:48                     ` Simon Wright
  2020-09-17 13:31                       ` Daniel
  0 siblings, 1 reply; 32+ messages in thread
From: Simon Wright @ 2020-09-16 21:48 UTC (permalink / raw)


I still don't understand _why_.

Purely from the visibility aspect,

package API is
   function F return Integer;
private
   Secret : constant := 42;
end API;

private package API.Impl is
   Altered : constant := Secret / 2;
end API.Impl;

with API.Impl;
package body API is
   function F return Integer is (Impl.Altered);
end API;

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

* Re: Visibility issue
  2020-09-16 21:48                     ` Simon Wright
@ 2020-09-17 13:31                       ` Daniel
  2020-09-17 15:00                         ` Dmitry A. Kazakov
  2020-09-18  8:05                         ` Simon Wright
  0 siblings, 2 replies; 32+ messages in thread
From: Daniel @ 2020-09-17 13:31 UTC (permalink / raw)


El miércoles, 16 de septiembre de 2020 a las 23:48:34 UTC+2, Simon Wright escribió:
> I still don't understand _why_. 
¿Why a tagged type in a callback function to send data to users?
It wasn't my decision. It's an imposed requirement.
(...yes sometimes I don't understand some requirements/limitations neither.)

> Purely from the visibility aspect, 
> 
> package API is 
> function F return Integer; 
> private 
> Secret : constant := 42; 
> end API; 
> 
> private package API.Impl is 
> Altered : constant := Secret / 2; 
> end API.Impl; 
> 
> with API.Impl; 
> package body API is 
> function F return Integer is (Impl.Altered); 
> end API;

ok Lets try to fit this requirement:
>"There will be one or more internal packages not visible to users where information is created. Preferably not in API hierarchy"
Let's ignore for now "why" this requirement and how reasonable is it. For example lets think for that the information comes from a data link implemented in other packages different to API.
In your example, all data is generated and processed within API packages, but the requirement obligates the data generated outside have to be send to users through API elements. (API just process it, but not generate it)

package Internal is
Secret : Natural :=0;
procedure Create_Data is
begin
   Secret :=Secret + 1;
end Create_Data;

You need to give this Data to Users using API. Let's think in easy example where Data gived to Users is Secret_Data / 2.

¿How is the better way to do it and in the same time not affect too much they way users see and use the API?



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

* Re: Visibility issue
  2020-09-17 13:31                       ` Daniel
@ 2020-09-17 15:00                         ` Dmitry A. Kazakov
  2020-09-17 15:32                           ` Daniel
  2020-09-18  8:05                         ` Simon Wright
  1 sibling, 1 reply; 32+ messages in thread
From: Dmitry A. Kazakov @ 2020-09-17 15:00 UTC (permalink / raw)


On 17/09/2020 15:31, Daniel wrote:
> El miércoles, 16 de septiembre de 2020 a las 23:48:34 UTC+2, Simon Wright escribió:
>> I still don't understand _why_.
> ¿Why a tagged type in a callback function to send data to users?
> It wasn't my decision. It's an imposed requirement.
> (...yes sometimes I don't understand some requirements/limitations neither.)
> 
>> Purely from the visibility aspect,
>>
>> package API is
>> function F return Integer;
>> private
>> Secret : constant := 42;
>> end API;
>>
>> private package API.Impl is
>> Altered : constant := Secret / 2;
>> end API.Impl;
>>
>> with API.Impl;
>> package body API is
>> function F return Integer is (Impl.Altered);
>> end API;
> 
> ok Lets try to fit this requirement:
>> "There will be one or more internal packages not visible to users where information is created. Preferably not in API hierarchy"

1. API.Impl is not in the public hierarchy of API.

2. Alternatively rename API.Impl into API_Impl. Move all secrets from 
API to API_Impl. Use API_Impl with the body of API.

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

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

* Re: Visibility issue
  2020-09-17 15:00                         ` Dmitry A. Kazakov
@ 2020-09-17 15:32                           ` Daniel
  2020-09-17 16:47                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 32+ messages in thread
From: Daniel @ 2020-09-17 15:32 UTC (permalink / raw)


El jueves, 17 de septiembre de 2020 a las 17:00:38 UTC+2, Dmitry A. Kazakov escribió:
> On 17/09/2020 15:31, Daniel wrote: 
> > El miércoles, 16 de septiembre de 2020 a las 23:48:34 UTC+2, Simon Wright escribió: 
> >> I still don't understand _why_. 
> > ¿Why a tagged type in a callback function to send data to users? 
> > It wasn't my decision. It's an imposed requirement. 
> > (...yes sometimes I don't understand some requirements/limitations neither.) 
> > 
> >> Purely from the visibility aspect, 
> >> 
> >> package API is 
> >> function F return Integer; 
> >> private 
> >> Secret : constant := 42; 
> >> end API; 
> >> 
> >> private package API.Impl is 
> >> Altered : constant := Secret / 2; 
> >> end API.Impl; 
> >> 
> >> with API.Impl; 
> >> package body API is 
> >> function F return Integer is (Impl.Altered); 
> >> end API; 
> > 
> > ok Lets try to fit this requirement: 
> >> "There will be one or more internal packages not visible to users where information is created. Preferably not in API hierarchy"
> 1. API.Impl is not in the public hierarchy of API. 
Sadly requirement says to dont be neither public or private hierarchy part of the API.

> 2. Alternatively rename API.Impl into API_Impl. Move all secrets from 
> API to API_Impl. Use API_Impl with the body of API.
¿How exactly achieve to use API_Imp with the body of API?.... maybe using " .."separate" keyword an using nested child ?
Something like this?
----api.ads
package body API is
package body API_Imp is separate;

--api-api_Imp.ads
separate (API)
package body API_Imp is
Secret:  Natural:= 42; 
Altered : Natural:= Secret / 2; 
end 
If is not like this example, ¿How is your proposal? 

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

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

* Re: Visibility issue
  2020-09-11 10:37 Visibility issue Daniel
                   ` (3 preceding siblings ...)
  2020-09-14 16:18 ` Simon Wright
@ 2020-09-17 15:58 ` Jere
  2020-09-17 16:10 ` Jere
  2020-09-17 21:47 ` Shark8
  6 siblings, 0 replies; 32+ messages in thread
From: Jere @ 2020-09-17 15:58 UTC (permalink / raw)


On Friday, September 11, 2020 at 6:37:29 AM UTC-4, Daniel wrote:
> Hello, 
> I want to use a tagged type as a link to communicate users of a library, in the way to make one part visible to them and also to hide some content that is only needed for the implementing of the library. 
> 
> Lets say i have the "Library" packages to expose things to users, and Implementing_Library packages to deal with the implementation: 
> 
> package Library.Users is 
> type User_type is tagged with private; 
> procedure foo_public (S: User_Type); 
> private 
> type User_Type is tagged with record 
> hide_content_to_user : Natural; 
> end record; 
> function Access_to_hide_content return User_type; 
> end Library.Users; 
> 
> private with Library.Users; 
> package Internal_Library_Implementing is 
> -- Some internal public developer stuff 
> private 
> --Here I want to get access to User_Type hide content. 
> end Internal_Library_Implementing; 
> 
> I've tried using "private with" but gnat says the next: 
> move subprogram to the visible part (RM 3.9.3(10)) 
> private function with tagged result must override visible-part function 
> 
> Compiler says Im forced to make all private User_type functions public. 
> So, are there more ways to see the hided content of this tagged type without extending the type itself in a child package? I needed to see this content outside of Library package.

Ada does not have a solution for the way you want to do it directly.  Languages like C++ (soon) 
and Java (already) have private modules (which are not the same as private packages), but 
Ada does not have an equivalent.  Now most compilers have a way to create a shared or static 
library and you can leverage this to get a similar scenario with Ada.  I would recommend 
a couple of different options:

1.  Break your design up more:
First make a singular package with public functions for both registering an implementation and
registering a client.  This holds your data structure where the callbacks are stored and searched
for and has low level data type calls for both a client and a implementer.

Next make two separate API packages, one for what you expect a client maker to use and one
for what an implementation maker might use.  These have high level data type and public
functions and they isolate all the client functionality to the client API package and all the 
implementer functionality to the implementer functionality  package.  Both of those will
internally (in the package body) use the low level calls from the first package I mentioned.

Finally, make either a static or shared library using these 3 packages and only expose the 
client API and the implementer API but not the low level package I first mentioned.  You
can then add that library to your normal code base and it is usable by the rest of your
code.

2.  Using package hierarchies.  Note, I know what your requirements you specified, but
if you are working inside Ada, then you are stuck using languages features provided by
it.  Others have suggested this, but I wanted to highlight this is the way I would probably
go at it because it makes sense with the type of design you are describing.  Make a top level
package that has all the low level stuff needed for both clients and implements in
the private section of that package.  I'll call it Base for simplicity.  Next, create your API hierarchy
as child packages under Base:  Base.Client_API for clients and then add an implementor child 
packages API also under Base:  Base.Implementer_API.  These both have access to the private
details of Base and also split up the public functions into two separate packages, one for 
clients and one for implementers.  Names can be obviously changed.

I realize that this doesn't meet your requirements completely, but Ada doesn't have any
analog to private modules (again not the same as private packages).  The first option
is most like what you want as you can use the library to hide the low level code and
only expose what public types and functions you want.  I provided the second option
because despite your requirements, that is the way I would tackle it as it clearly links
the relationships between everything similar to how the design is laid out.

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

* Re: Visibility issue
  2020-09-11 10:37 Visibility issue Daniel
                   ` (4 preceding siblings ...)
  2020-09-17 15:58 ` Jere
@ 2020-09-17 16:10 ` Jere
  2020-09-18  8:08   ` Simon Wright
  2020-09-17 21:47 ` Shark8
  6 siblings, 1 reply; 32+ messages in thread
From: Jere @ 2020-09-17 16:10 UTC (permalink / raw)


On Friday, September 11, 2020 at 6:37:29 AM UTC-4, Daniel wrote:
> Hello, 
> I want to use a tagged type as a link to communicate users of a library, in the way to make one part visible to them and also to hide some content that is only needed for the implementing of the library. 
> 
> Lets say i have the "Library" packages to expose things to users, and Implementing_Library packages to deal with the implementation: 
> 
> package Library.Users is 
> type User_type is tagged with private; 
> procedure foo_public (S: User_Type); 
> private 
> type User_Type is tagged with record 
> hide_content_to_user : Natural; 
> end record; 
> function Access_to_hide_content return User_type; 
> end Library.Users; 
> 
> private with Library.Users; 
> package Internal_Library_Implementing is 
> -- Some internal public developer stuff 
> private 
> --Here I want to get access to User_Type hide content. 
> end Internal_Library_Implementing; 
> 
> I've tried using "private with" but gnat says the next: 
> move subprogram to the visible part (RM 3.9.3(10)) 
> private function with tagged result must override visible-part function 
> 
> Compiler says Im forced to make all private User_type functions public. 
> So, are there more ways to see the hided content of this tagged type without extending the type itself in a child package? I needed to see this content outside of Library package.

One side note and I hope you don't take this comment negatively but instead as a chance
to improve communication:  

I started out trying to take what you provided and figure out a solution and quickly 
realized that I would need to take hours to create an example to even work with
because none of the examples you provided were close to compilable.  I quickly
gave up and moved to higher level discussion.  If you really want more direct answers
consider making a small fully compilable example for people to play with and make
adjustments too.  For things you want but wouldn't compile, place inline comments 
in your code clearly specifying what you want to change or what is missing.  That
gives others a workable template to play with.  They can take your example, 
compile it and then make changes to try and implement some of the requirements
better without having to guess at what you really want.

Again, not saying that to be negative, but wanted to at least give that feedback to
help you get better answers in the future.

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

* Re: Visibility issue
  2020-09-17 15:32                           ` Daniel
@ 2020-09-17 16:47                             ` Dmitry A. Kazakov
  0 siblings, 0 replies; 32+ messages in thread
From: Dmitry A. Kazakov @ 2020-09-17 16:47 UTC (permalink / raw)


On 17/09/2020 17:32, Daniel wrote:
> El jueves, 17 de septiembre de 2020 a las 17:00:38 UTC+2, Dmitry A. Kazakov escribió:
>> On 17/09/2020 15:31, Daniel wrote:
>>> El miércoles, 16 de septiembre de 2020 a las 23:48:34 UTC+2, Simon Wright escribió:
>>>> I still don't understand _why_.
>>> ¿Why a tagged type in a callback function to send data to users?
>>> It wasn't my decision. It's an imposed requirement.
>>> (...yes sometimes I don't understand some requirements/limitations neither.)
>>>
>>>> Purely from the visibility aspect,
>>>>
>>>> package API is
>>>> function F return Integer;
>>>> private
>>>> Secret : constant := 42;
>>>> end API;
>>>>
>>>> private package API.Impl is
>>>> Altered : constant := Secret / 2;
>>>> end API.Impl;
>>>>
>>>> with API.Impl;
>>>> package body API is
>>>> function F return Integer is (Impl.Altered);
>>>> end API;
>>>
>>> ok Lets try to fit this requirement:
>>>> "There will be one or more internal packages not visible to users where information is created. Preferably not in API hierarchy"
>> 1. API.Impl is not in the public hierarchy of API.
> Sadly requirement says to dont be neither public or private hierarchy part of the API.

Private child has exactly same semantic as the private part of API 
package. A requirement cannot forbid one yet allow another. If it does 
fire the guy who wrote it for incompetence.

>> 2. Alternatively rename API.Impl into API_Impl. Move all secrets from
>> API to API_Impl. Use API_Impl with the body of API.

package API is
    ...
end API;

with API_Impl;
package body API is
   ...
end API;

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

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

* Re: Visibility issue
  2020-09-11 10:37 Visibility issue Daniel
                   ` (5 preceding siblings ...)
  2020-09-17 16:10 ` Jere
@ 2020-09-17 21:47 ` Shark8
  6 siblings, 0 replies; 32+ messages in thread
From: Shark8 @ 2020-09-17 21:47 UTC (permalink / raw)


On Friday, September 11, 2020 at 4:37:29 AM UTC-6, Daniel wrote:
> Hello, 
> I want to use a tagged type as a link to communicate users of a library, in the way to make one part visible to them and also to hide some content that is only needed for the implementing of the library.

Here's how that's normally achieved; I've compiled the following but haven't written a testbed/driver:

-- Daniel.ads
Package Daniel with Pure is
   -- Base Interface which all API objects implement.
   Type Abstract_Base is interface;
   
   -- All common methods.
   Function As_String(Object : Abstract_Base) return String is abstract;
   
   -- All Classwide methods.
   Function Print( Object : Abstract_Base'Class ) return String;
   
   
   -- The Callback type.
   Type Callback is access
     procedure(Item : in out Abstract_Base'Class);
   
Private
   -- The classwide "Print" returns the given object's As_String result.
   Function Print( Object : Abstract_Base'Class ) return String is
      (Object.As_String);
End Daniel;

-----------------------------------------------
-- Daniel-Implementation.ads
With
Ada.Finalization,
Ada.Strings.Equal_Case_Insensitive,
Ada.Strings.Less_Case_Insensitive,
Ada.Containers.Indefinite_Ordered_Maps;

Private Package Daniel.Implementation with Preelaborate is
   -- Fwd decl.
   Type Implementation_Base(Name_Length : Positive) is tagged private;
   
   -- Implementation_Base and its descendents have a Name, that is within the
   -- private-portion of the implementation and therefore we need an accessor.
   -- Note: Name is unique and case-insensitive.
   Function Get_Name(Object: Implementation_Base'Class) Return String;

   -- Given a name, this retrieves the object; raises constraint-error if that
   -- name is not associated with an object.
   Function Make  (Name : String) return Implementation_Base'Class;
   Function Create(Name : String) return Implementation_Base;
   Function "="(Left, Right : Implementation_Base) return Boolean;
   
Private
   -- Full decl. Note, also, that this is hidden from the API package.
   Type Implementation_Base(Name_Length : Positive) is
     new Ada.Finalization.Controlled with record
      Name : String(1..Name_Length);
   End record;
   
   -- Finalization; this will remove the registered Name from the object-map.
   overriding
   procedure Finalize   (Object : in out Implementation_Base);

   -- Instantiate the package mapping Names to Objects.
   Package Name_Map is new Ada.Containers.Indefinite_Ordered_Maps(
         Key_Type     => String,
         Element_Type => Implementation_Base'Class,
         "<" => Ada.Strings.Less_Case_Insensitive,
         "=" => "="
        );
   
   -- This is the map that associates objects and their names.
   Core_Map : Name_Map.Map;
End Daniel.Implementation;

------------------------------------------------
-- Daniel-API.ads
Private With
Daniel.Implementation;

Private Package Daniel.API with Preelaborate is
   -- The base API-visable type.
   Type API_Base(<>) is new Abstract_Base with private;
   
   -- Creation functions.
   Function Create(Name : String) return API_Base;
   Function Create(Name : String; Op : Callback) return API_Base;
   
   -- Interface functions.
   Function As_String (Object :        API_Base) return String;
   Procedure Execute  (Object : in out API_Base);
Private
   -- We derive from implementation's base, and add a discriminant for the
   -- callback and another fata-field.
   Type API_Base( CBK : Callback; Length : Positive ) is
     new Daniel.Implementation.Implementation_Base( Name_Length => Length )
     and Abstract_Base with record
      A_1 : Character := 'C';
   end record;
   
   -- We raise an exception when there is no callback given.
   Function Create(Name : String) return API_Base is
     (raise Program_Error with "Callback MUST be specified.");
   
   -- Finally, we construct an object from a call to implementation's create
   -- and fill-in the missing information using an "extension aggrigate".
   Function Create(Name : String; Op : Callback) return API_Base is
     (Implementation.Create(Name) with
      CBK => Op, Length => Name'Length, others => <>);
   
End Daniel.API;

------------------------------------------------------------------------------
-- Daniel-Implementation.adb
with
Ada.Exceptions,
Ada.Finalization;

use
Ada.Finalization;

Package Body Daniel.Implementation is
   Function "=" (Left, Right : String) return Boolean
    renames Ada.Strings.Equal_Case_Insensitive;
   
   Function Get_Name(Object: Implementation_Base'Class) Return String is
     (Object.Name);

   Function Make(Name : String) return Implementation_Base'Class is
   Begin
      Return Core_Map(Name);
   Exception
      when PE : Program_Error =>
         raise Constraint_Error with Ada.Exceptions.Exception_Message(PE);
   End Make;

   Function "="(Left, Right : Implementation_Base) return boolean is
      (Left.Name = Right.Name);
   
   Function Create(Name : String) return Implementation_Base is
   begin
      Return Result : Constant Implementation_Base :=
        (Controlled with Name_Length => Name'Length, Name => Name) do
         Core_Map.Include(New_Item => Result, Key => Name);
      end return;
   end Create;
   
   Procedure Finalize(Object : in out Implementation_Base) is
   Begin
      Core_Map.Delete( Object.Name );
   End Finalize;
   
End Daniel.Implementation;

------------------------------------------------------
-- Daniel-API.adb
Package Body Daniel.API is
   Procedure Execute  (Object : in out API_Base) is
   Begin
      Object.CBK.All(Object);
   End Execute;

   Function As_String (Object : in API_Base) return String is
   Begin
      Return '(' & Object.Get_Name & ", " & Object.A_1 & ')';
   End As_String;
End Daniel.API;

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

* Re: Visibility issue
  2020-09-17 13:31                       ` Daniel
  2020-09-17 15:00                         ` Dmitry A. Kazakov
@ 2020-09-18  8:05                         ` Simon Wright
  1 sibling, 0 replies; 32+ messages in thread
From: Simon Wright @ 2020-09-18  8:05 UTC (permalink / raw)


Daniel <danielnorberto@gmail.com> writes:

> ok Lets try to fit this requirement:
>>"There will be one or more internal packages not visible to users
>> where information is created. Preferably not in API hierarchy"
> Let's ignore for now "why" this requirement and how reasonable is
> it. For example lets think for that the information comes from a data
> link implemented in other packages different to API.

I can't ignore this "requirement" (well, I can ignore it in practice,
because it's just an intellectual puzzle that someone (an educator?) has
dreamt up).

A customer who says "we would give preference to Ada-based solutions,
because we believe they will be better" is being reasonable.

Of course, it may be that you have a customer who knows how to do this
in C++, and is challenging you to replicate that solution in Ada.

> In your example, all data is generated and processed within API
> packages, but the requirement obligates the data generated outside
> have to be send to users through API elements. (API just process it,
> but not generate it)

Come on, it's only a toy example! The private child packages can do
anything that's needed, communicate with databases,, AI, ...

And, to reiterate what Dmitry says, (a) private child packages are *not*
part of the API, (b) my point in using them was to show that they are
the way to get access to the private parts of the public API.

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

* Re: Visibility issue
  2020-09-17 16:10 ` Jere
@ 2020-09-18  8:08   ` Simon Wright
  0 siblings, 0 replies; 32+ messages in thread
From: Simon Wright @ 2020-09-18  8:08 UTC (permalink / raw)


Jere <jhb.chat@gmail.com> writes:

> I started out trying to take what you provided and figure out a
> solution and quickly realized that I would need to take hours to
> create an example to even work with because none of the examples you
> provided were close to compilable.

And those hours might result in something that wasn't even near what you
wanted.

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

end of thread, other threads:[~2020-09-18  8:08 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-11 10:37 Visibility issue Daniel
2020-09-11 11:51 ` Maxim Reznik
2020-09-11 20:11   ` Daniel
2020-09-11 14:23 ` Jeffrey R. Carter
2020-09-11 20:17   ` Daniel
2020-09-11 22:36     ` Jeffrey R. Carter
2020-09-14 10:47       ` Daniel
2020-09-14 16:10         ` Jeffrey R. Carter
2020-09-15 19:11           ` Daniel
2020-09-15 20:03             ` Jeffrey R. Carter
2020-09-11 21:05 ` Dmitry A. Kazakov
2020-09-14 11:33   ` Daniel
2020-09-14 14:42     ` Dmitry A. Kazakov
2020-09-15 19:35       ` Daniel
2020-09-16  7:14         ` Dmitry A. Kazakov
2020-09-16 10:23           ` Daniel
2020-09-16 10:58             ` Dmitry A. Kazakov
2020-09-16 14:35               ` Daniel
2020-09-16 14:49                 ` Jeffrey R. Carter
2020-09-16 15:05                 ` Dmitry A. Kazakov
2020-09-16 20:09                   ` Daniel
2020-09-16 21:48                     ` Simon Wright
2020-09-17 13:31                       ` Daniel
2020-09-17 15:00                         ` Dmitry A. Kazakov
2020-09-17 15:32                           ` Daniel
2020-09-17 16:47                             ` Dmitry A. Kazakov
2020-09-18  8:05                         ` Simon Wright
2020-09-14 16:18 ` Simon Wright
2020-09-17 15:58 ` Jere
2020-09-17 16:10 ` Jere
2020-09-18  8:08   ` Simon Wright
2020-09-17 21:47 ` Shark8

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