Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem instantiating a package with subtype access to variant record

Tags:

generics

ada

I try to compile an Ada 95 program with an Ada 2012 compiler. However there are problems with instantiation of the generic package Garbage_Collector. The subtype A_Term is not accepted in the package instantiation:

prolog.adb:27:15: designated type of actual does not match that of formal "Link"
prolog.adb:27:15: instantiation abandoned

I have tried to change A_Term to type A_Term is access A_Node;. Then the package will instantiate, but the rest of the code breaks. Has something changed since Ada 95 and how can I make it work in Ada 2012?

procedure Prolog is

   generic
      type Item is limited private;
      type Link is access Item;
   package Garbage_Collector is
      procedure Get (L : in out Link) is null;
   end Garbage_Collector;

   type Node_Tag is (A, B);

   type Node (Tag : Node_Tag);
   type Term is access Node;

   type Node (Tag : Node_Tag) is
      record
         case Tag is
            when A => null;
            when B => null;
         end case;
      end record;

   subtype A_Node is Node (A);
   subtype A_Term is Term (A);
   package Gc_A is new Garbage_Collector
     (Item => A_Node,
      Link => A_Term);

   T : Term;
begin
   Gc_A.Get (T);
end Prolog;

The code is from a Prolog module from Stanford University. The project on GitHub

like image 938
Jesper Quorning Avatar asked May 03 '21 14:05

Jesper Quorning


2 Answers

I can't say what exactly causes your error. It could well be that this is a compiler bug. To fix this in a minimal invasive way, I suggest to make the access relation invisible to the generic unit:

procedure Prolog is

   generic
      type Item is limited private;
      type Link is private;
      with function Deref (L : Link) return Item is <>;
   package Garbage_Collector is
      procedure Get (L : in out Link) is null;
   end Garbage_Collector;

   type Node_Tag is (A, B);

   type Node (Tag : Node_Tag);
   type Term is access Node;

   type Node (Tag : Node_Tag) is
      record
         case Tag is
            when A => null;
            when B => null;
         end case;
      end record;

   subtype A_Node is Node (A);
   subtype A_Term is Term (A);
   
   function Deref (L : A_Term) return A_Node is (L.all);
   
   package Gc_A is new Garbage_Collector
     (Item  => A_Node,
      Link  => A_Term);

   T : Term;
begin
   Gc_A.Get (T);
end Prolog;

Now the compiler does not complain because the formal type Link is not an access type anymore and has no relation to Item. By giving the function Deref, you are still able to dereference an object of type Link. You will need an additional function if you need to assign to it.

like image 160
flyx Avatar answered Oct 28 '22 15:10

flyx


In your code sample above, you declare types Node and Term:

type Node (Tag : Node_Tag);
type Term is access Node;

You then attempt to declare two subtypes:

subtype A_Node is Node (A);
subtype A_Term is Term (A);

The declaration of subtype A_Node makes sense, since Node is a discriminant type. The declaration of subtype A_Term does not make sense. Type Term is access Node, which is different from type Node. Try changing the declaration of subtype A_Term to:

subtype A_Term is access A_Node;
like image 41
Jim Rogers Avatar answered Oct 28 '22 16:10

Jim Rogers