comp.lang.ada
 help / color / mirror / Atom feed
* pointers and genericity
@ 2005-02-15 12:10 Xavier Serrand
  2005-02-15 13:12 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 8+ messages in thread
From: Xavier Serrand @ 2005-02-15 12:10 UTC (permalink / raw)


Hello cruel word,

I would like to use pointers to procedures in a generic package ... ok
no problem
But i want another generic package to use this... and i can't because
the pointer type must be in the body of a generic package...

I KNOW that I can use genericity to bypass the problem... but is it
possible to change the value of the generic parameters after the
instanciation (as I can do with pointers variables)?

generic
  type T_Elem is private
  Null_Elem : in T_Elem;
package Pk_DataSource is
   type T_proc_Browse is access procedure (E : in out T_Record; S :
out string);
   type T_Record is
      Data : T_Elem;
      Next : T_Proc_Browse;
      Prev : T_Proc_Browse;
   end record;
end Pk_DataSource;

generic
  type T_Element is private
  Null_Element : in T_Element;
  with package Pk_DS is new Pk_DataSource (T_Elem => T_Element,
                                           Null_Elem => Null_Element);
package Pk_User is
   type T_User is
      Nom : string (1..33) := (others => ' ');
      Rec : Pk_DS.T_Record := (Data => Null_Element, Next, Prev =>
null);
   end record;
   procedure Assign (U : in out T_User; 
                     S : in string; E : in T_Element;
                     Proc_Next, Proc_Prev : in Pk_DS.T_Proc_Browse);
end Pk_User;

--=========================================
-- All is ok !!
-- But i can't make this in Pk_User's body :
--=========================================

package Pk_User body is

   procedure Assign (U : in out T_User; 
                     S : in string; E : in T_Element;
                     Proc_Next, Proc_Prev : in Pk_DS.T_Proc_Browse) is
   begin
      U.Nom(1..Min(U.Nom'Last, S'Last)) := S(1..Min(U.Nom'Last,
S'Last));
      U.Rec.Data := E;
      -- and now some trouble !!
      U.Rec.Next := Proc_Next;
      U.Rec.Prev := Proc_Prev;
   end;
End Pk_User;



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

* Re: pointers and genericity
  2005-02-15 12:10 pointers and genericity Xavier Serrand
@ 2005-02-15 13:12 ` Dmitry A. Kazakov
  2005-02-16  9:27   ` Xavier Serrand
  0 siblings, 1 reply; 8+ messages in thread
From: Dmitry A. Kazakov @ 2005-02-15 13:12 UTC (permalink / raw)


On 15 Feb 2005 04:10:38 -0800, Xavier Serrand wrote:

> Hello cruel word,
> 
> I would like to use pointers to procedures in a generic package ... ok
> no problem
> But i want another generic package to use this... and i can't because
> the pointer type must be in the body of a generic package...
> 
> I KNOW that I can use genericity to bypass the problem... but is it
> possible to change the value of the generic parameters after the
> instanciation (as I can do with pointers variables)?
> 
> generic
>   type T_Elem is private
>   Null_Elem : in T_Elem;
> package Pk_DataSource is
>    type T_proc_Browse is access procedure (E : in out T_Record; S :
> out string);
>    type T_Record is
>       Data : T_Elem;
>       Next : T_Proc_Browse;
>       Prev : T_Proc_Browse;
>    end record;
> end Pk_DataSource;
> 
> generic
>   type T_Element is private
>   Null_Element : in T_Element;
>   with package Pk_DS is new Pk_DataSource (T_Elem => T_Element,
>                                            Null_Elem => Null_Element);
> package Pk_User is
>    type T_User is
>       Nom : string (1..33) := (others => ' ');
>       Rec : Pk_DS.T_Record := (Data => Null_Element, Next, Prev =>
> null);
>    end record;
>    procedure Assign (U : in out T_User; 
>                      S : in string; E : in T_Element;
>                      Proc_Next, Proc_Prev : in Pk_DS.T_Proc_Browse);
> end Pk_User;
> 
> --=========================================
> -- All is ok !!
> -- But i can't make this in Pk_User's body :
> --=========================================
> 
> package Pk_User body is
> 
>    procedure Assign (U : in out T_User; 
>                      S : in string; E : in T_Element;
>                      Proc_Next, Proc_Prev : in Pk_DS.T_Proc_Browse) is
>    begin
>       U.Nom(1..Min(U.Nom'Last, S'Last)) := S(1..Min(U.Nom'Last,
> S'Last));
>       U.Rec.Data := E;
>       -- and now some trouble !!
>       U.Rec.Next := Proc_Next;
>       U.Rec.Prev := Proc_Prev;

So far it is legal, (ignoring some minor errors with missing "record" after
"is", misplaced "body" and necessary forward declaration of "T_Record".

>    end;
> End Pk_User;

It is not clear what you want to achieve. Should Assign work with T_Record
from all possible instances of Pk_DataSource? If so, then you have to
switch to tagged types.

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



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

* Re: pointers and genericity
  2005-02-15 13:12 ` Dmitry A. Kazakov
@ 2005-02-16  9:27   ` Xavier Serrand
  2005-02-16  9:35     ` Martin Dowie
                       ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Xavier Serrand @ 2005-02-16  9:27 UTC (permalink / raw)


You are right... trouble comes from that

package body Test_Gen_Pk_User  is

   function Min (A, B : in Natural) return Natural is
   begin
      if (A < B) then
         return A;
      else
         return B;
      end if;
   end;
   procedure Proc_Suiv (E : in out Pk_DS.T_Record; 
                        S : out string) is
   begin
      S := (others => ' ');
   end;

   procedure Assign (U : in out T_User; 
                     S : in string; E : in T_Element;
                     Proc_Next, Proc_Prev : in Pk_DS.T_Proc_Browse) is
   begin
      U.Nom(1..Min(U.Nom'Last, S'Last)) := S(1..Min(U.Nom'Last,
S'Last));
      U.Rec.Data := E;
      U.Rec.Prev := Proc_Prev;
      if not Pk_DS."=" (Proc_Prev, null) then
         U.Rec.Next := Proc_Next;
      else
         -- ***********************
         -- and now some trouble !!
         -- ***********************
         U.Rec.Next := Proc_Suiv'access;
      end if;
   end;
End Test_Gen_Pk_User ;

==============Error messages for source file:
test/test_gen_pk_user.adb
    30.          U.Rec.Next := Proc_Suiv'access;
                               |
        >>> access type must not be outside generic body



-- and the correct packages

generic
  type T_Elem is private;
  Null_Elem : in T_Elem;
package Test_Gen_Pk_DataSource is
   type T_Record;
   type T_proc_Browse is access procedure (E : in out T_Record; 
                                           S : out string);
   type T_Record is record
      Data : T_Elem;
      Next : T_Proc_Browse;
      Prev : T_Proc_Browse;
   end record;
end Test_Gen_Pk_DataSource ;

with Test_Gen_Pk_DataSource;
generic
  type T_Element is private;
  Null_Element : in T_Element;
  with package Pk_DS is new Test_Gen_Pk_DataSource (T_Elem =>
T_Element,
                                                    Null_Elem =>
Null_Element);
package Test_Gen_Pk_User is
   type T_User is record
      Nom : string (1..33) := (others => ' ');
      Rec : Pk_DS.T_Record := (Data => Null_Element, 
                               Next => null, Prev => null);
   end record;
   procedure Assign (U : in out T_User; 
                     S : in string; E : in T_Element;
                     Proc_Next, Proc_Prev : in Pk_DS.T_proc_Browse);
end Test_Gen_Pk_User;


with Test_Gen_Pk_DataSource;
with Test_Gen_Pk_User; 

procedure Test_Gen_Prg_User is
   package Pack_DS is new Test_Gen_Pk_DataSource (T_Elem => Character,
                                                  Null_Elem => ' ');


   package Pack_US is new Test_Gen_Pk_User (T_Element => Character,
                                            Null_Element => ' ',
                                            Pk_DS => Pack_DS);
   procedure Proc_Suivant (E : in out Pack_DS.T_Record; 
                           S : out string) is
   begin
      S := (1 => E.Data, others => ' ');
      E.Data := Character'Val (Character'Pos(E.Data)+1);
   end;
begin
   declare
      U : Pack_US.T_User;
   begin
      Pack_US.Assign (U, "joe", 'a', null, null);
   end;
end;

In fact i would like to make scrollable data sources controlled by
event handlers (basic package) and some uses like arborescent menus,
data visualisation...



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

* Re: pointers and genericity
  2005-02-16  9:27   ` Xavier Serrand
@ 2005-02-16  9:35     ` Martin Dowie
  2005-02-16  9:53     ` Egil H. H�vik
  2005-02-16 15:00     ` Robert A Duff
  2 siblings, 0 replies; 8+ messages in thread
From: Martin Dowie @ 2005-02-16  9:35 UTC (permalink / raw)


Xavier Serrand wrote:
>       E.Data := Character'Val (Character'Pos(E.Data)+1);

E.Data := Character'Succ (E.Data);

?






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

* Re: pointers and genericity
  2005-02-16  9:27   ` Xavier Serrand
  2005-02-16  9:35     ` Martin Dowie
@ 2005-02-16  9:53     ` Egil H. H�vik
  2005-02-16 15:00     ` Robert A Duff
  2 siblings, 0 replies; 8+ messages in thread
From: Egil H. H�vik @ 2005-02-16  9:53 UTC (permalink / raw)


Have you tried:


"Xavier Serrand" <xavier.serrand@free.fr> wrote in message
news:344d0fee.0502160127.432c8614@posting.google.com...
> You are right... trouble comes from that
>
<snip>
> with Test_Gen_Pk_DataSource;
> generic
>   type T_Element is private;
>   Null_Element : in T_Element;
>   with package Pk_DS is new Test_Gen_Pk_DataSource (T_Elem =>
> T_Element,
>                                                     Null_Elem =>
> Null_Element);
> package Test_Gen_Pk_User is
>    type T_User is record
>       Nom : string (1..33) := (others => ' ');
>       Rec : Pk_DS.T_Record := (Data => Null_Element,
>                                Next => null, Prev => null);
>    end record;
>    procedure Assign (U : in out T_User;
>                      S : in string; E : in T_Element;
>                      Proc_Next, Proc_Prev : in Pk_DS.T_proc_Browse);

private
   procedure Proc_Suiv (E : in out Pk_DS.T_Record;
                        S : out string);

> end Test_Gen_Pk_User;


~egilhh





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

* Re: pointers and genericity
  2005-02-16  9:27   ` Xavier Serrand
  2005-02-16  9:35     ` Martin Dowie
  2005-02-16  9:53     ` Egil H. H�vik
@ 2005-02-16 15:00     ` Robert A Duff
  2005-02-17 22:50       ` Xavier Serrand
  2005-02-17 23:11       ` Randy Brukardt
  2 siblings, 2 replies; 8+ messages in thread
From: Robert A Duff @ 2005-02-16 15:00 UTC (permalink / raw)


xavier.serrand@free.fr (Xavier Serrand) writes:

> ==============Error messages for source file:
> test/test_gen_pk_user.adb
>     30.          U.Rec.Next := Proc_Suiv'access;
>                                |
>         >>> access type must not be outside generic body

If the access type is outside the generic body, then it's illegal
to take 'Access of a procedure declared inside the generic body.
The workaround is to declare the procedure in the generic
package spec.  If you don't want to export it, put it in
the private part.

I think the reason for this rule has something to do with making it
easier to implement code sharing of generic bodies.

I didn't look at your code carefully, but sometimes it's cleaner to use
a tagged type with a dispatching procedure, rather than an
access-to-procedure, because then you can easily package up
some data with the procedure.

- Bob



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

* Re: pointers and genericity
  2005-02-16 15:00     ` Robert A Duff
@ 2005-02-17 22:50       ` Xavier Serrand
  2005-02-17 23:11       ` Randy Brukardt
  1 sibling, 0 replies; 8+ messages in thread
From: Xavier Serrand @ 2005-02-17 22:50 UTC (permalink / raw)


thanks for that advise Bob!!

in fact what i would like to do has to do with packagged data ... but
i would like to implement those functionality without any objet
feature...

I made an "object-like" menu in c with struct and
"access-to-procedure" ... somthing very poor for my TI89... and i
wonder if i could make more object-like WITHOUT any object feature...
Almost everything is possible with Ada 83 + very few... and i would
like to proof it for my own sake...

Xavier

Robert A Duff <bobduff@shell01.TheWorld.com> wrote in message news:<wccsm3wo8hv.fsf@shell01.TheWorld.com>...
> xavier.serrand@free.fr (Xavier Serrand) writes:
> 
> > ==============Error messages for source file:
> > test/test_gen_pk_user.adb
> >     30.          U.Rec.Next := Proc_Suiv'access;
> >                                |
> >         >>> access type must not be outside generic body
> 
> If the access type is outside the generic body, then it's illegal
> to take 'Access of a procedure declared inside the generic body.
> The workaround is to declare the procedure in the generic
> package spec.  If you don't want to export it, put it in
> the private part.
> 
> I think the reason for this rule has something to do with making it
> easier to implement code sharing of generic bodies.
> 
> I didn't look at your code carefully, but sometimes it's cleaner to use
> a tagged type with a dispatching procedure, rather than an
> access-to-procedure, because then you can easily package up
> some data with the procedure.
> 
> - Bob



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

* Re: pointers and genericity
  2005-02-16 15:00     ` Robert A Duff
  2005-02-17 22:50       ` Xavier Serrand
@ 2005-02-17 23:11       ` Randy Brukardt
  1 sibling, 0 replies; 8+ messages in thread
From: Randy Brukardt @ 2005-02-17 23:11 UTC (permalink / raw)



"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
news:wccsm3wo8hv.fsf@shell01.TheWorld.com...
...
> If the access type is outside the generic body, then it's illegal
> to take 'Access of a procedure declared inside the generic body.
> The workaround is to declare the procedure in the generic
> package spec.  If you don't want to export it, put it in
> the private part.
>
> I think the reason for this rule has something to do with making it
> easier to implement code sharing of generic bodies.

The root reason for the rule is to avoid contract problems with the
accessibility checks. (As it says in the AARM!). Unlike objects,
accessibility checks for subprograms are always done at compile-time. Since
we don't know where the generic will be instantiated, and we never look in
bodies after the template is compiled, we need an assume-the-worst rule for
the check. This is it.

Yes, it makes the implementation easier, but that's not the only (or even
major) motivation. Note that this rule was changed in Ada 2005 (AI-229)
because it still allowed the creation of dangling pointers. In so doing, we
also relaxed it a bit.

                  Randy.







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

end of thread, other threads:[~2005-02-17 23:11 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-02-15 12:10 pointers and genericity Xavier Serrand
2005-02-15 13:12 ` Dmitry A. Kazakov
2005-02-16  9:27   ` Xavier Serrand
2005-02-16  9:35     ` Martin Dowie
2005-02-16  9:53     ` Egil H. H�vik
2005-02-16 15:00     ` Robert A Duff
2005-02-17 22:50       ` Xavier Serrand
2005-02-17 23:11       ` Randy Brukardt

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