Question

In an implementation of "boxed types" (for an interpreter) I originally had vectors in a child package and used System.Access_To_Address_Conversions to convert from System.Address to Vector_Ptr as needed in order to avoid seemingly insurmountable problems with cyclic dependencies. (At least, no use of limited with every did the trick for me.) It worked but seemed like a nasty hack. So I've decided to put the container types into the main package Types.Boxed. Now GNAT complains 'no declaration in visible part for incomplete type "Vector" defined at line 12'

Is there any way to fix this? Or should I return to my nasty hack?

Ada 2005 using GNAT 4.6 with flag -gnat05

with Interfaces; use Interfaces;
with Ada.Strings.Wide_Unbounded; use Ada.Strings.Wide_Unbounded;
with Ada.Containers.Vectors;
with Green_Tasks; use Green_Tasks;

package Types.Boxed is

   type Type_T is (T_Null, T_Unsigned_64, T_String, T_Boolean,
                   T_Green_Task, T_Vector);

   type String_Ptr is access all Unbounded_Wide_String;
   type Vector;
   type Vector_Ptr is access all Vector;

     type Item (IType : Type_T := T_Null) is record
        case IType is
        when T_Null        => null;
        when T_Unsigned_64 => Value_Unsigned_64  : Unsigned_64;
        when T_String      => Value_String       : String_Ptr;
        when T_Boolean     => Value_Boolean      : Boolean;
        when T_Green_Task  => Value_Green_Task   : Green_Task_Ptr;
        when T_Vector      => Value_Vector       : Vector_Ptr;
        end case;
   end record;

   procedure Free (Datum : in out Item);
   procedure Box (Datum : out Item; Value : in Unsigned_64);
   function Unbox (Datum : Item) return Unsigned_64;
   procedure Box (Datum : out Item; Value : String_Ptr);
   function Unbox (Datum : Item) return String_Ptr;
   procedure Box (Datum : out Item; Value : in Boolean);
   function Unbox (Datum : Item) return Boolean;
   procedure Box (Datum : out Item; Value : in Green_Task_Ptr);
   function Unbox (Datum : Item) return Green_Task_Ptr;
   function Get_Boxed_Type (Datum : Item) return Type_T;

   -- vectors
    package Item_Vectors is new Ada.Containers.Vectors
     ( Index_Type   => Natural,
      Element_Type => Item
     );
   use Item_Vectors;


   function Vector_New (Size_Hint : Positive) return Item;
   function Unbox (Datum : Item) return Vector_Ptr;
   procedure Vector_Free (V : in out Vector_Ptr);
   function Vector_Copy (V : Vector_Ptr) return Item;

   pragma Inline (Box);
   pragma Inline (Unbox);
   pragma Pure_Function (Unbox);
   pragma Pure_Function (Get_Boxed_Type);


end Types.Boxed;
Was it helpful?

Solution

OK, I assume that you thought when you instantiated Item_Vectors and said use Item_Vectors, that the Vector type in Item_Vectors would be the completion of the incomplete Vector you wrote earlier.

It doesn't. When you say use P, it means that all the names defined in P are now directly visible, so if P declares a type T, you can say T instead of saying P.T. But the symbols still belong to P. They do not become "part of" the package that contains the use. Thus, for instance, use Item_Vectors; means that you can say Empty_Cursor instead of Item_Vectors.Empty_Cursor. But there will not be a Types.Boxed.Empty_Cursor. The name still belongs to Item_Vectors.

What this means is that when you have an incomplete Vector type in Types.Boxed, there needs to be a completion in Types.Boxed. The Vector type in Item_Vectors does not become the completion of the type, and the use doesn't help with that.

Unfortunately, Ada doesn't let you complete the type with a "type rename" or a subtype. The best option I can think of is

type Vector is new Item_Vectors.Vector with null record;

Note that this causes all the operations in Item_Vector to be inherited for Vector. So this might work for you. But there could be some unanticipated problems. But I can't think of a better solution.

EDIT: It looks like Simon has a good possible solution.

OTHER TIPS

I played around with this and found that I could get it to compile by making Item_Vectors of element type Item_Ptr:

type Item (<>);
type Item_Ptr is access all Item;

package Item_Vectors is new Ada.Containers.Vectors
 ( Index_Type   => Natural,
   Element_Type => Item_Ptr
  );
subtype Vector is Item_Vectors.Vector;
type Vector_Ptr is access all Vector;

type Item (IType : Type_T := T_Null) is record
   case IType is
      when T_Null        => null;
      when T_Unsigned_64 => Value_Unsigned_64  : Unsigned_64;
      when T_String      => Value_String       : String_Ptr;
      when T_Boolean     => Value_Boolean      : Boolean;
      when T_Vector      => Value_Vector       : Vector_Ptr;
     end case;
end record;

(I removed Green_Tasks, hopefully not relevant to your problem).

I was interested to see from ARM 3.10.1(3) that the complete declaration can only be postponed to the body if the incomplete declaration is in the private part.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top