comp.lang.ada
 help / color / mirror / Atom feed
* Tagged types and static dispatching
@ 1996-12-02  0:00 Tobias Ritzau
  1996-12-02  0:00 ` Paul Chardon
  1996-12-05  0:00 ` John English
  0 siblings, 2 replies; 3+ messages in thread
From: Tobias Ritzau @ 1996-12-02  0:00 UTC (permalink / raw)



Hi everyone!

I have some trouble understanding some featers of Ada 95. I wrote a
small package with a linked list and a list iterator. Of course I wanted
the types to be tagged so that I could expand them later on. When I
compiled my package I got an error message saying:
  operation can be displatching in only one type
The error was on the restart procedure below.

package list is
 
   type List is tagged private;
   type ListIt is tagged private;
 
   procedure insert(l : in out List; el : in T);
   function length(l : in List) return Natural;
  
   procedure restart(li : in out ListIt; l : in List);
   procedure next(li : in out ListIt);
   function atend(li : in ListIt) return Boolean;
   function item(li : in ListIt) return T;

private
   ...
 
I removed the tagged keyword from the iterator and then everything
compiled ok. Then I reinserted the tagged word and replaced the
parameter types by ListIt'Class and List'Class and again everything
compiled ok.
If I have understood things correctly the Class attributes enables
dynamic binding and I don't want to use dynaimc binding. Why can't I use
two tagged types as parameters to a sub-program? What is the correct way
to do this?

Thank you for helping me

Tobias Ritzau




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

* Re: Tagged types and static dispatching
  1996-12-02  0:00 Tagged types and static dispatching Tobias Ritzau
@ 1996-12-02  0:00 ` Paul Chardon
  1996-12-05  0:00 ` John English
  1 sibling, 0 replies; 3+ messages in thread
From: Paul Chardon @ 1996-12-02  0:00 UTC (permalink / raw)
  To: Tobias Ritzau


Tobias Ritzau wrote:
> 
> Hi everyone!
> 
> I have some trouble understanding some featers of Ada 95. I wrote a
> small package with a linked list and a list iterator. Of course I wanted
> the types to be tagged so that I could expand them later on. When I
> compiled my package I got an error message saying:
>   operation can be displatching in only one type
> The error was on the restart procedure below.
> 
> package list is
> 
>    type List is tagged private;
>    type ListIt is tagged private;
> 
>    procedure insert(l : in out List; el : in T);
>    function length(l : in List) return Natural;
> 
>    procedure restart(li : in out ListIt; l : in List);
>    procedure next(li : in out ListIt);
>    function atend(li : in ListIt) return Boolean;
>    function item(li : in ListIt) return T;
> 
> private
>    ...
> 
> I removed the tagged keyword from the iterator and then everything
> compiled ok. Then I reinserted the tagged word and replaced the
> parameter types by ListIt'Class and List'Class and again everything
> compiled ok.
> If I have understood things correctly the Class attributes enables
> dynamic binding and I don't want to use dynaimc binding. Why can't I use
> two tagged types as parameters to a sub-program? What is the correct way
> to do this?
> 
> Thank you for helping me
> 
> Tobias Ritzau

Hello, 

	When you are defining a tagged types and operations about this types,
each operation must contain only one parameter of this type to be a
primitive operation, that is to say an operation on which you can do
dispatching. This parameter is called a CHOICE PARAMETER. This parameter
is the basis of the dispatching which use the tag of the type to choose
the correct operation to invoke.
	If you build an operation with two parammeters of the tagged type, the
compiler won't be able to find which tag to use to construct the
dispatching call. Another criteria will be need to select the good
parameter tag. So such an operation is not a primitive operation of the
tagged type, no dispatching for it and it won't be inherited.
	On the contrary what you can do (described in RM and ARM) is
dispatching and redispatching which use primitive operations including
parameter of another class wide type, and then the dispatching operation
has got two class-wide type parameters. But I think read some examples
on the rationale if you've got it, it is very well explained. I even
give you an example from it.

This example from the Rationale will perhaps help you to construct you
list handler.

package Doubly_Linked is

   type Node_Type is tagged limited private;

   type Node_Ptr is access all Node_Type'Class;

   -- define add/remove operations,
   -- assuming head of list is a single Node_Ptr
   procedure Add(Item: Node_Ptr; Head: in out Node_Ptr);
   -- add new node at head of list

   procedure Remove(Item: Node_Ptr; Head: in out Node_Ptr);
   -- remove node from list, update Head if necessary

   -- define functions to iterate forward or backward over list
   function Next(Item: Node_Ptr) return Node_Ptr;

   function Prev(Item: Node_Ptr) return Node_Ptr;

private

   type Node_Type is tagged limited
      record
	 Prev: Node_Ptr := null;
	 Next: Node_Ptr := null;
	 -- other components to be added by extension
      end record;

end Doubly_Linked;

with Ada.Unchecked_Deallocation;
package body Doubly_Linked is

   -- define add/remove operations,
   -- assuming head of list is a single Node_Ptr
   procedure Add(Item: Node_Ptr; Head: in out Node_Ptr) is
      First : Node_Ptr := Head;
   begin
      if (Head /= null) then
	 Head.Prev := Item;
	 Head := Item;
	 Head.Next := First;
      else
	 Head := Item;
	 Head.Prev := null;
	 Head.Next := null;
      end if;
   end Add;
   -- add new node at head of list

   procedure Remove(Item: Node_Ptr; Head: in out Node_Ptr) is
      Current : Node_Ptr := Head;
      procedure Remove_Node is 
	new Ada.Unchecked_Deallocation(Node_Type'Class,Node_Ptr);
   begin
      if (Item = Head) then
	 Head := Item.Next;
	 Current := Item;
	 Remove_Node   -- define functions to iterate forward
or 	                        -- backward over list(Current);
      else
	 loop
	    exit when (Current = null);
	    exit when (Current = Item);
	    Current := Current.Next;
	 end loop;

	 if (Current /= null) then
	    Current.Prev.Next := Item.Next;
	    Remove_Node(Current);
	 end if;
      end if;	 
   end Remove;

   function Next(Item: Node_Ptr) return Node_Ptr is
   begin
      return Item.Next;
   end Next;

   function Prev(Item: Node_Ptr) return Node_Ptr is
   begin
      return Item.Prev;
   end Prev;   

end Doubly_Linked;


	Hope it will help you, Paul.




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

* Re: Tagged types and static dispatching
  1996-12-02  0:00 Tagged types and static dispatching Tobias Ritzau
  1996-12-02  0:00 ` Paul Chardon
@ 1996-12-05  0:00 ` John English
  1 sibling, 0 replies; 3+ messages in thread
From: John English @ 1996-12-05  0:00 UTC (permalink / raw)



Tobias Ritzau (Tobias.Ritzau@masda.hv.se) wrote:
: I have some trouble understanding some featers of Ada 95. I wrote a
: small package with a linked list and a list iterator. Of course I wanted
: the types to be tagged so that I could expand them later on. When I
: compiled my package I got an error message saying:
:   operation can be displatching in only one type

Yes, since you have the two tagged types declared in the same pacakge
spec, you're asking the compiler is trying to make Restart a primitive
operation of *both* types.

Possible solutions:
1) Make ListIt non-tagged, so Restart only has one tagged parameter and
   so is only a primitive of List (as you found out)
2) Use a class-wide parameter so again Restart has only one tagged
   parameter and is only a primitive of List
3) Declare the types in different package specifications so Restart
   is only a primitive of the type declared in the same specification.

The advantage of (2) is that you can do double dispatching (selecting
a primitive operation based on two independent tagged values) like so:

  procedure Restart(I : in out ListIt'Class; L : in List) is
     -- calls dispatch to the appropriate version of Restart depending
     -- on the actual type of L
  begin
     ListIt_Primitive(I);	-- dispatches to the appropriate
				-- ListIt operation depending on
				-- the actual type of I
  end Restart;
---------------------------------------------------------------
 John English              | mailto:je@brighton.ac.uk
 Senior Lecturer           | http://www.comp.it.bton.ac.uk/je
 Dept. of Computing        | fax: (+44) 1273 642405
 University of Brighton    |
---------------------------------------------------------------




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

end of thread, other threads:[~1996-12-05  0:00 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-12-02  0:00 Tagged types and static dispatching Tobias Ritzau
1996-12-02  0:00 ` Paul Chardon
1996-12-05  0:00 ` John English

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