Ada 详细说明根本没有发生
Ada elaboration not occurring at all
我有一个不寻常的情况,其中精化代码根本没有被执行。这不是细化顺序问题,而是细化所有问题。
问题是我没有 "with" 任何有问题的单元,但理论上它应该仍然可以访问,只要它的详细说明发生。
当然,我可以为有问题的单元添加一个无用的 "with",但在我的实际用例中,我必须对大量单元进行处理。
我的问题是,在代码中,通过 pragmas,在 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;
编译器认为您的包 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
子句。
我不知道是否有不太明显的解决方案。如果有,它可能是特定于编译器的。但我不确定为什么编译器会有一项功能,可以让您将原本未使用的包合并到程序中。
我所做的(例如 here ff)是实际引用主程序中的单元(使用 pragma Unreferenced
以防止警告)。
或者,您可以有一个包裹,例如Required_Units
包含所有必要的 with
,然后 with
来自主程序。
即使有一些替代过程,你也必须告诉它你需要包括哪些单位;不妨顺其自然,在Ada中做!
由于程序包 Bs 对您的程序不可见,因此类型 B 也是如此。
那么下一个问题是:如果没有任何地方使用,为什么还需要注册类型B?
如果 Ada 编译器确实详细说明了与主程序无关但通过源路径可见的所有单元(包或独立子程序),那将变得非常混乱!...
我有一个不寻常的情况,其中精化代码根本没有被执行。这不是细化顺序问题,而是细化所有问题。
问题是我没有 "with" 任何有问题的单元,但理论上它应该仍然可以访问,只要它的详细说明发生。
当然,我可以为有问题的单元添加一个无用的 "with",但在我的实际用例中,我必须对大量单元进行处理。
我的问题是,在代码中,通过 pragmas,在 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;
编译器认为您的包 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
子句。
我不知道是否有不太明显的解决方案。如果有,它可能是特定于编译器的。但我不确定为什么编译器会有一项功能,可以让您将原本未使用的包合并到程序中。
我所做的(例如 here ff)是实际引用主程序中的单元(使用 pragma Unreferenced
以防止警告)。
或者,您可以有一个包裹,例如Required_Units
包含所有必要的 with
,然后 with
来自主程序。
即使有一些替代过程,你也必须告诉它你需要包括哪些单位;不妨顺其自然,在Ada中做!
由于程序包 Bs 对您的程序不可见,因此类型 B 也是如此。
那么下一个问题是:如果没有任何地方使用,为什么还需要注册类型B?
如果 Ada 编译器确实详细说明了与主程序无关但通过源路径可见的所有单元(包或独立子程序),那将变得非常混乱!...