comp.lang.ada
 help / color / mirror / Atom feed
* Loosing tagged type via linked list
@ 2008-02-09  1:05 jason.height
  2008-02-09  3:48 ` Georg Bauhaus
  2008-02-09  9:38 ` Dmitry A. Kazakov
  0 siblings, 2 replies; 5+ messages in thread
From: jason.height @ 2008-02-09  1:05 UTC (permalink / raw)


Hi All,

I have an interesting problem where i need to store a bunch of
procedure calls (for graphics displays) and the associated parameters
for later calling (much like a macro call).

I am attempting this in Ada95, with my own Linked_List container impl,
which seems to be destroying the type information. If anyone knows a
Ada95 list implementation that can store items of different types
(derived from a base type) then please let me know.

Ideally i would like the following method to always print B_Type:
--------------------------------------------------------------------------------------------
with Text_Io;
with Ada.Tags; use Ada.Tags;
with Linked_List;

procedure Test is
  type A_Type is tagged record
    null;
  end record;
  type B_Type is new A_Type with record
    Int : Integer;
  end record;

  A : A_Type;
  B : B_Type := (Int => 1);

  package MyList is new Linked_List(A_Type);
  The_List : MyList.List_Type;
  Itr : MyList.List_Iterator;

  procedure DoPrint(Input : A_Type'Class) is
  begin
    Text_Io.Put_Line("Tag is "&Expanded_Name(Input'Tag));
  end;
  procedure DoPrintTypeCast(Input : A_Type) is
  begin
    DoPrint(Input);
  end;
begin

  --These all print TEST.B_Type
  DoPrint(B);
  DoPrint(A_Type(B));
  DoPrintTypeCast(A_Type(B));

  --This prints TEST.A_Type!
  --BAD List Impl?
  MyList.Add(The_List, A_Type(B));
  Itr := MyList.First(The_List);
  DoPrint(MyList.Value(Itr));
end;
------------------------------------------------------------------------------------

Here is the list spec. I was hoping that someone could spot my trouble
right off. I must admit i am more at home with Java and C#, where the
containers are built into the platform, so this one has had me stumped
for a few days.

------------------------------------------------------------------------------------------------------------------------------
with Ada.Finalization; use Ada.Finalization;
generic
   type Item_Type is tagged private;
package Linked_List is
   type List_Type is new Limited_Controlled with private;
   type List_Iterator is private;

   function First (List : List_Type) return List_Iterator;

   function Value (Iterator : List_Iterator) return Item_Type'Class;

   procedure Add (List : in out List_Type; Item : in Item_Type);

private
   type Item_Record;
   type Item_Access is access Item_Record;

   type Item_Record is record
      Item : Item_Type;
      Next : Item_Access := null;
      Pred : Item_Access := null;
   end record;
   type List_Header is record
      First : Item_Access := null;
      Last  : Item_Access := null;
      Count : Natural := 0;
   end record;
   type List_Access is access List_Header;

   type List_Type is new Limited_Controlled with record
      List : List_Access := new List_Header;
   end record;

   procedure Finalize (Object : in out List_Type);

   type List_Iterator is record
      List    : List_Access := null;
      Current : Item_Access := null;
   end record;
end Linked_List;
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Thanks in advance
Jason



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

* Re: Loosing tagged type via linked list
  2008-02-09  1:05 Loosing tagged type via linked list jason.height
@ 2008-02-09  3:48 ` Georg Bauhaus
  2008-02-09 11:40   ` Simon Wright
  2008-02-09  9:38 ` Dmitry A. Kazakov
  1 sibling, 1 reply; 5+ messages in thread
From: Georg Bauhaus @ 2008-02-09  3:48 UTC (permalink / raw)


jason.height@gmail.com wrote:

Looks like an issue with copying into a record component
in the generic list. Copying would be unlike parameter passing.
While tagged objects are passed by reference, assigning to a
variable of a specific type copies a value of the target
type. Only the relevant components of the target type stay.

Consider this:

with Ada.Tags;
with Ada.Text_IO;

procedure Main is

    package Type_Hier is

        type A_Type is tagged null record;

        procedure DoPrint(The_Item: A_Type);
        -- print The_Items's actual tag

        type B_Type is new A_Type with null record;

    end Type_Hier;


    package body Type_Hier is

        procedure DoPrint(The_Item: A_Type) is
            use Ada;
            Whoami: A_Type'Class renames A_Type'Class(The_Item);
        begin
            Text_IO.put_line("Tag is " &
                Tags.Expanded_Name(Whoami'Tag));
        end DoPrint;

    end Type_Hier;



    use Type_Hier;


    Object: A_Type;
    -- this would be the Item_Type component of Item_Record

begin  -- Main

    DoPrint(A_Type'(null record));
    DoPrint(A_Type(B_Type'(null record)));  -- A_Type view

    Object := A_Type(B_Type'(null record));
      -- not a reference, neither just an A_Type view, but a copy
      -- of the A_Type parts

    DoPrint(Object);

end Main;

$ ./main
Tag is MAIN.TYPE_HIER.A_TYPE
Tag is MAIN.TYPE_HIER.B_TYPE
Tag is MAIN.TYPE_HIER.A_TYPE

One solution would be to use references to classwide types,
somewhat like Java.


> I am attempting this in Ada95, with my own Linked_List container impl,
> which seems to be destroying the type information. If anyone knows a
> Ada95 list implementation that can store items of different types
> (derived from a base type) then please let me know.

The Booch components will let you do this, using indefinite
generic formal types.
http://sourceforge.net/project/showfiles.php?group_id=135616.
(The WiKi seems out of order at this time; doc is contained in
an accompanying archive.)

The Charles library is the predecessor of Ada 2005's container
library, http://charles.tigris.org/ . There is a subdirectory
ai302 which has an Ada 95 implementation of containers for
indefinite types, too.

HTH,
 -- Georg



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

* Re: Loosing tagged type via linked list
  2008-02-09  1:05 Loosing tagged type via linked list jason.height
  2008-02-09  3:48 ` Georg Bauhaus
@ 2008-02-09  9:38 ` Dmitry A. Kazakov
  1 sibling, 0 replies; 5+ messages in thread
From: Dmitry A. Kazakov @ 2008-02-09  9:38 UTC (permalink / raw)


On Fri, 8 Feb 2008 17:05:58 -0800 (PST), jason.height@gmail.com wrote:

> I have an interesting problem where i need to store a bunch of
> procedure calls (for graphics displays) and the associated parameters
> for later calling (much like a macro call).
> 
> I am attempting this in Ada95, with my own Linked_List container impl,
> which seems to be destroying the type information. If anyone knows a
> Ada95 list implementation that can store items of different types
> (derived from a base type) then please let me know.
> 
> Ideally i would like the following method to always print B_Type:
> --------------------------------------------------------------------------------------------
> with Text_Io;
> with Ada.Tags; use Ada.Tags;
> with Linked_List;
> 
> procedure Test is
>   type A_Type is tagged record
>     null;
>   end record;
>   type B_Type is new A_Type with record
>     Int : Integer;
>   end record;
> 
>   A : A_Type;
>   B : B_Type := (Int => 1);
> 
>   package MyList is new Linked_List(A_Type);

This is the problem (or else a question) with your design. What is *the*
type of list items? Are they from A_Type or from A_Type'Class? Note that
these aren't same. (Unlikely to Java Ada is properly typed, so any object
has just one type)

My guess is that you wanted A_Type'Class. In that case the package
Linked_List need to be designed correspondingly and instantiated as

    package MyList is new Linked_List (A_Type'Class);

[ It can also be designed so that an instantiation looked

    package MyList is new Linked_List (A_Type);
       -- We say A_Type but actually mean A_Type'Class ]

>   The_List : MyList.List_Type;
>   Itr : MyList.List_Iterator;
> 
>   procedure DoPrint(Input : A_Type'Class) is
>   begin
>     Text_Io.Put_Line("Tag is "&Expanded_Name(Input'Tag));
>   end;
>   procedure DoPrintTypeCast(Input : A_Type) is
>   begin
>     DoPrint(Input);
>   end;
> begin
> 
>   --These all print TEST.B_Type
>   DoPrint(B);
>   DoPrint(A_Type(B));
>   DoPrintTypeCast(A_Type(B));
> 
>   --This prints TEST.A_Type!
>   --BAD List Impl?
>   MyList.Add(The_List, A_Type(B));
>   Itr := MyList.First(The_List);
>   DoPrint(MyList.Value(Itr));
> end;
> ------------------------------------------------------------------------------------
> 
> Here is the list spec. I was hoping that someone could spot my trouble
> right off. I must admit i am more at home with Java and C#, where the
> containers are built into the platform, so this one has had me stumped
> for a few days.
> 
> ------------------------------------------------------------------------------------------------------------------------------
> with Ada.Finalization; use Ada.Finalization;
> generic
>    type Item_Type is tagged private;
> package Linked_List is
>    type List_Type is new Limited_Controlled with private;
>    type List_Iterator is private;
> 
>    function First (List : List_Type) return List_Iterator;
> 
>    function Value (Iterator : List_Iterator) return Item_Type'Class;
> 
>    procedure Add (List : in out List_Type; Item : in Item_Type);
> 
> private
>    type Item_Record;
>    type Item_Access is access Item_Record;
> 
>    type Item_Record is record
>       Item : Item_Type;

This causes your problem. The type of Item is Item_Type and it becomes
A_Type upon instantiation. Note that semantically it should be:

       Item : Item_Type'Class;

which were illegal in Ada. Note that the following is also illegal:

   generic
       type Item_Type is (<>) private; -- This can take A_Type'Class
   package Linked_List is
       type Item_Record is record
           Item : Item_Type;

In both cases Item_Record were unconstrained and the compiler has no idea
where to get the constraint from. For this reason (with this particular
design) you have to use a pointer to Item_Type'Class (or to Item_Type when
unconstrained) instead. Upon copying a copy has to be allocated on the heap
and the list item should keep a pointer to it. When the item gets deleted
the copy it points to has to be freed.

Simple Components provide an Ada 95 implementation of lists. The items can
be of any type, including unconstrained ones (A_Type'Class is
unconstrained):

http://www.dmitry-kazakov.de/ada/components.htm#Generic_Doubly_Linked_Web

Differently to conventional designs like yours Simple Components do not
copy list items, but allocates them only once.

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



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

* Re: Loosing tagged type via linked list
  2008-02-09  3:48 ` Georg Bauhaus
@ 2008-02-09 11:40   ` Simon Wright
  2008-02-10 17:11     ` Simon Wright
  0 siblings, 1 reply; 5+ messages in thread
From: Simon Wright @ 2008-02-09 11:40 UTC (permalink / raw)


Georg Bauhaus <see.reply.to@maps.futureapps.de> writes:

> jason.height@gmail.com wrote:

>> I am attempting this in Ada95, with my own Linked_List container impl,
>> which seems to be destroying the type information. If anyone knows a
>> Ada95 list implementation that can store items of different types
>> (derived from a base type) then please let me know.
>
> The Booch components will let you do this, using indefinite
> generic formal types.
> http://sourceforge.net/project/showfiles.php?group_id=135616.

If you want to use a definite formal type, then access-to-classwide is
what you need (there will have to be an access under the hood,
whatever solution you adopt).

  type A_Type_P is access A_Type'Class;

Allocation and, more challengingly perhaps, deallocation are then up
to you.

> (The WiKi seems out of order at this time; doc is contained in
> an accompanying archive.)

So it is. First time I've heard! Can't be visited very often ...



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

* Re: Loosing tagged type via linked list
  2008-02-09 11:40   ` Simon Wright
@ 2008-02-10 17:11     ` Simon Wright
  0 siblings, 0 replies; 5+ messages in thread
From: Simon Wright @ 2008-02-10 17:11 UTC (permalink / raw)


Simon Wright <simon.j.wright@mac.com> writes:

> Georg Bauhaus <see.reply.to@maps.futureapps.de> writes:

>> (The WiKi seems out of order at this time; doc is contained in
>> an accompanying archive.)
>
> So it is. First time I've heard! Can't be visited very often ...

Now mostly migrated to SourceForge's native Wiki.



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

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

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-02-09  1:05 Loosing tagged type via linked list jason.height
2008-02-09  3:48 ` Georg Bauhaus
2008-02-09 11:40   ` Simon Wright
2008-02-10 17:11     ` Simon Wright
2008-02-09  9:38 ` Dmitry A. Kazakov

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