完全不进行Ada细化

时间:2019-02-20 22:15:12

标签: ada gnat

我有一种不寻常的情况,其中根本没有执行详细代码。这不是精化命令问题,而是所有问题的解决方法。

问题在于,无论如何我都不会“带着”该单元,但从理论上讲,只要进行详细说明,它仍然应该可以访问。

当然,我可以为有问题的单元添加一个无用的“ with”,但是在我的实际用例中,我将不得不使用大量的单元。

我的问题是代码中是否有任何方式,通过编译指示,在gpr项目文件中还是通过命令行开关,即使我认为编译器认为该文件不是,也可以强制编译器包括该文件被引用?

这是一个最小的工作示例:

as.ads:

package As is
    type A is tagged null record;
    type Nothing is null record;
    function Create (Ignored : not null access Nothing) return A;
    function Image (From : A) return String;
end As;

as.adb:

package body As is
    function Create (Ignored : not null access Nothing) return A is
        (null record);
    function Image (From : A) return String is ("A");
end As;

finder.ads:

with Ada.Tags;

package Finder is
    procedure Register (Name : String; Tag : Ada.Tags.Tag);
    function Find (Name : String; Default : Ada.Tags.Tag) return Ada.Tags.Tag;
end Finder;

finder.adb:

with Ada.Containers.Indefinite_Vectors;

package body Finder is
    type Name_Tag (Size : Natural) is
        record
            Name : String (1 .. Size);
            To : Ada.Tags.Tag;
        end record;

    package Name_Tag_Vectors is new Ada.Containers.Indefinite_Vectors (Positive, Name_Tag);
    Name_Tags : Name_Tag_Vectors.Vector := Name_Tag_Vectors.Empty_Vector;

    procedure Register (Name : String; Tag : Ada.Tags.Tag) is begin
        Name_Tags.Append ((Name'Length, Name, Tag));
    end Register;

    function Find (Name : String; Default : Ada.Tags.Tag) return Ada.Tags.Tag is begin
        for Tag of Name_Tags loop
            if Tag.Name = Name then
                return Tag.To;
            end if;
        end loop;

        return Default;
    end Find;
end Finder;

bs.ads:

with As;
package Bs is
    type B is new As.A with null record;
    function Create (Ignored : not null access As.Nothing) return B;
    function Image (From : B) return String;
end Bs;

bs.adb:

with Finder;
package body Bs is
    function Create (Ignored : not null access As.Nothing) return B is
        (As.Create (Ignored) with null record);
    function Image (From : B) return String is ("B");
begin
    Finder.Register ("B", B'Tag);
end Bs;

test.adb:

with As; use As;
-- with Bs; -- (uncommenting this line solves my problem, but what if I had the rest of the alphabet?)
with Finder;
with Ada.Tags.Generic_Dispatching_Constructor;
with Ada.Text_IO;

procedure Test is
    function Constructor is new Ada.Tags.Generic_Dispatching_Constructor (
        T => A,
        Parameters => Nothing,
        Constructor => Create);

    Nada : aliased Nothing := (null record);
    What : A'Class := Constructor (Finder.Find ("B", A'Tag), Nada'Access);
begin
    Ada.Text_IO.Put_Line (What.Image);
end Test;

3 个答案:

答案 0 :(得分:6)

编译器认为未引用您的软件包Bs,因为没有引用。您没有with子句,因此它不是程序的一部分。

一个简单的例子:

a.ads

package A is
    procedure Blah;
end A;

a.adb

with Ada.Text_IO;
package body A is
    procedure Blah is begin null; end Blah;
begin
    Ada.Text_IO.Put_Line("Elaborate A");
end A;

b.ads

package B is
    procedure Blah;
end B;

b.adb

with Ada.Text_IO;
package body B is
    procedure Blah is begin null; end Blah;
begin
    Ada.Text_IO.Put_Line("Elaborate B");
end B;

main.adb

with Ada.Text_IO;
with A;
procedure Main is
begin
    Ada.Text_IO.Put_Line("Main");
end Main;

当我运行main时,它会打印

Elaborate A
Main

它不会打印Elaborate B,因为该软件包不属于程序的一部分;它只是同一目录中的几个源文件。

显而易见的解决方案是添加with子句。

我不知道是否有一个不太明显的解决方案。如果存在,则可能是特定于编译器的。但是我不确定为什么编译器会具有允许您将原本未使用的程序包合并到程序中的功能。

答案 1 :(得分:3)

我所做的(例如here等)实际上是引用主程序中的单位(使用pragma Unreferenced来防止警告)。

或者,您可以拥有一个包装,例如Required_Units,其中包含所有必要的with,然后从主程序中with

即使有其他程序,您也必须告诉它需要包含哪些单位;不妨顺其自然,并在Ada中进行!

答案 2 :(得分:0)

由于程序包Bs对程序不可见,因此类型B也是如此。

接下来的问题是:如果类型B没有在任何地方使用,为什么还要注册它呢?

如果Ada编译器确实完成了与主程序无关的所有单元(程序包或独立子程序),但是它们在源路径中可见,那么它将变得非常混乱!...