实例化具有对变体记录的子类型访问权限的包时出现问题

Jes*_*ing 5 generics ada

我尝试使用 Ada 2012 编译器编译 Ada 95 程序。然而,通用包的实例化存在问题Garbage_CollectorA_Term包实例化中不接受子类型:

prolog.adb:27:15: designated type of actual does not match that of formal "Link"
prolog.adb:27:15: instantiation abandoned
Run Code Online (Sandbox Code Playgroud)

我尝试更改A_Termtype A_Term is access A_Node;. 然后包将实例化,但其余代码中断。自 Ada 95 以来发生了一些变化,我如何使其在 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;
Run Code Online (Sandbox Code Playgroud)

代码来自斯坦福大学的 Prolog 模块。GitHub 上的项目

fly*_*lyx 5

我不能说到底是什么导致了你的错误。这很可能是一个编译器错误。为了以最小的侵入性方式解决这个问题,我建议使access关系对通用单元不可见:

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;
Run Code Online (Sandbox Code Playgroud)

现在编译器不会抱怨,因为正式类型Link不再是访问类型并且与Item. 通过提供函数Deref,您仍然可以取消引用类型的对象Link。如果您需要分配给它,您将需要一个附加功能。


Jim*_*ers 3

在上面的代码示例中,您声明了类型NodeTerm

type Node (Tag : Node_Tag);
type Term is access Node;
Run Code Online (Sandbox Code Playgroud)

然后,您尝试声明两个子类型:

subtype A_Node is Node (A);
subtype A_Term is Term (A);
Run Code Online (Sandbox Code Playgroud)

的声明subtype A_Node是有道理的,因为Node它是一个判别类型。的声明subtype A_Term没有意义。TypeTermaccess Node,它与 type 不同Node。尝试将 的声明更改subtype A_Term为:

subtype A_Term is access A_Node;
Run Code Online (Sandbox Code Playgroud)