comp.lang.ada
 help / color / mirror / Atom feed
From: Damien Carbonne <damien.carbonne@free.fr>
Subject: Re: generic formal primitive [dispatching] operation
Date: 2000/09/19
Date: 2000-09-19T00:00:00+00:00	[thread overview]
Message-ID: <39C9282A.3865AC9C@free.fr> (raw)
In-Reply-To: 8q5c2e$gkt$1@melusine.cuivre.fr.eu.org

Thomas Quinot a �crit :

> Dans comp.lang.ada, Damien Carbonne  �crit :
>
> >I would like to create a generic package that has, as formal parameters,
> >a tagged type and some primitive dispatching operations on that type.
> >
> >I have tried this:
> >
> >generic
> >   type Root is abstract tagged private;
> >   with procedure P1 (This : access Root);
>
> P1 is not a primitive operation of Root, because in instances of your
> package, P1 denotes a view of the actual parameter, and does not
> declare a subprogram. The subprogram denoted by P1 is thus not
> declared in the same declarative_region as type Root, and therefore
> does not qualify to be a primitive operation of Root.
>
> It is unclear to me what you are trying to achieve. Could you be more
> specific about what you actually want to do?

Right, I will try to give a better description of the problem I have, and
why I created the example I gave previously.

I would like to create a package that looks like that:

-- generic_reference.ads
-------------------------------------------------------------------------------------------

with Ada.Finalization; use Ada.Finalization;

generic
   type Transformation is private;
   with function Identity return Transformation is <>;
   with function "*" (Left, Rigth : Transformation) return Transformation is
<>;

   type Transformer is abstract tagged limited private;
   -- Here I believe that these decalaration can match primitive operations
of Transformer
   with function Parent_To_Self (This : access Transformer) return
Transformation is <>;
   with function Self_To_Parent (This : access Transformer) return
Transformation is <>;
package Generic_References is

   pragma Elaborate_Body;

   type Transformer_Ref is access all Transformer'Class;

   type Reference is limited private;
   type Reference_Ptr is access all Reference;

   procedure Set_Parent
     (This   : access Reference;
      Parent : in     Reference_Ptr);

   procedure Set_Transformer
     (This        : access Reference;
      Transformer : in     Transformer_Ref);

   function Transformation_Betweeen
     (Ref_1 : access Reference;
      Ref_2 : access Reference)
      return Transformation;

private

   -- Here I want to derive Root and redefine dispatching operations.
   type Identity_Transformer is new Transformer with null record;
   function Parent_To_Self (This : access Identity_Transformer) return
Transformation;
   function Self_To_Parent (This : access Identity_Transformer) return
Transformation;

   G_Identity_Transformer : Transformer_Ref := new Identity_Transformer;

   type Reference is new Limited_Controlled with record
      null;
   end record;

   procedure Initialize (Obj : in out Reference);
   procedure Finalize   (Obj : in out Reference);

end Generic_References;
-------------------------------------------------------------------------------------------

The objective is to handle the notion of Reference attached to a body, and
to provide a simple
way to make any location or velocity or acceleration etc ...changes between
two any references.

From this package point of view, a Transformation must only have two
operations:
1) composition
2) Identity

Such a Transformation can be imagined in any Space (2D, 3D, etc) or anything
else that has no direct
geometric interpretation.

The Transformer type must be viewed as a java-like interface. Its role is to
provide the
transformations between two References (via Parent_To_Self and
Self_To_Parent).

Initially I had not declared Identity_Transformer in the spec. As I had the
error I mentioned
previously in the body, I changed the formal part with:

   type Transformer is abstract tagged limited private;
   with function Parent_To_Self (This : access Transformer'Class) return
Transformation is <>;
   with function Self_To_Parent (This : access Transformer'Class) return
Transformation is <>;

But then , when I declared the derived type Identity_Transformer I had other
errors with overriding
of operations of Transformer.

So, in fact I happen to ask myself what was the difference between:
   type Root is abstract tagged private;
   with procedure P1 (This : access Root);

and:
   type Root is abstract tagged private;
   with procedure P1 (This : access Root'Class);

The first solution seems to allow derivation (Identity_Transformer) and to
handle dispatching, but
I don't know how to use the operations in the body, whilst the second
solution reverses the problem.

I know that if the Transformer type was defined in the spec of the generic
there would not be any
problem. But I don't want to do it for the following reason:
The actual Transformer type may derive or not from a base type. And I don't
want to write two
versions of the package, one with a base type, and the other without any
base type. This is why
I would like to define a formal generic "interface" (abstract class
+ operations) that can be
"implemented" or derived in the generic (e.g., Identity_Transformer) and
that can be used in the body!

As I have not found any clear (for me) explanation in the RM about formal
primitive operations, I
tried simple examples (I know, examples are not proof!) like:
------------------------------------------------------
generic
   type Root is abstract tagged private;
   with procedure P1 (This : access Root);
package Generic_Deriveds is
   type Derived is new Root with null record;
   procedure P1 (This : access Derived);
end Generic_Deriveds;

with Ada.Text_IO;
package body Generic_Deriveds is
   procedure P1 (This : access Derived) is
   begin
      Ada.Text_IO.Put_Line("Generic_Deriveds.Derived.P1");
   end P1;
end Generic_Deriveds;

package Roots is
   type Root is tagged null record;
   procedure P1 (This: access Root);
end Roots;

with Ada.Text_IO;
package body Roots is
   procedure P1 (This: access Root) is
   begin
      Ada.Text_IO.Put_Line("Roots.Root.P1");
   end P1;
end Roots;

with Roots;
with Generic_Deriveds;
package Deriveds is new Generic_Deriveds(Roots.Root, Roots.P1);

with Roots; use Roots;
with Deriveds; use Deriveds;
procedure Main is
   R : aliased Root;
   D : aliased Derived;
   procedure Check (This : access Root'Class) is
   begin
      P1(This);
   end Check;
begin
   Check(R'Access);
   Check(D'Access);
end Main;
-------------------------------------------------------

Using gnat 3.13a, this compiles and works as I expect (at least I believe it
!), it prints:
Roots.Root.P1
Generic_Deriveds.Derived.P1

And, if I suppress the definition of P1 in Generic_Deriveds, the output is:
Roots.Root.P1
Roots.Root.P1

So this example makes me think that in the declaration:
generic
   type Root is abstract tagged private;
   with procedure P1 (This : access Root);
P1 is a (or may be) interpreted by the compiler as a primitive operation.

The only problem I have is the one illustrated in the first post: I can not
use dispatching in the body
(or I don't know how to do it)

I am afraid to be  bit confusing, but I would really like to understand this
issue.

I whish someone could clarify all this for me!

Thanks !

Damien.





  reply	other threads:[~2000-09-19  0:00 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <39C5321E.805A73D1@free.fr>
2000-09-18  0:00 ` generic formal primitive [dispatching] operation Thomas Quinot
2000-09-19  0:00   ` Damien Carbonne [this message]
2000-09-18  0:00 ` Robert A Duff
2000-09-19  0:00   ` Damien Carbonne
2000-09-19  0:00     ` Robert A Duff
replies disabled

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