(Ada)火花中的冰点问题
我有以下套餐:(Ada)火花中的冰点问题,ada,gnat,Ada,Gnat,我有以下套餐: ------------------- -- File: father.ads ------------------- package Father with SPARK_Mode => On is pragma Elaborate_Body; type Father_T is abstract tagged private; function Get_Field_1 (Self : Father_T) return Positive;
-------------------
-- File: father.ads
-------------------
package Father with SPARK_Mode => On is
pragma Elaborate_Body;
type Father_T is abstract tagged private;
function Get_Field_1 (Self : Father_T) return Positive;
procedure Proc_1 (Self : in out Father_T; Another : Father_T) is abstract;
function Func_1 (Self : Father_T) return Boolean is abstract;
private
pragma SPARK_Mode (Off);
type Father_T is abstract tagged record
Field_1 : Positive := 1;
end record;
end Father;
--------------------------
-- File: father-middle.ads
--------------------------
package Father.Middle with SPARK_Mode => On is
pragma Elaborate_Body;
type Middle_T is abstract new Father_T with null record; -- [L1]
overriding procedure Proc_1 (Self : in out Middle_T; Another : Middle_T);
private
pragma SPARK_Mode (Off);
function Func_2 (Self : Middle_T) return Boolean;
end Father.Middle; -- [L3]
--------------------------
-- File: father-middle.adb
--------------------------
package body Father.Middle is
------------
-- Proc_1 --
------------
overriding procedure Proc_1 (Self : in out Middle_T; Another : Middle_T) is -- [L2]
begin
Self.Field_1 := Self.Field_1 + Another.Field_1;
end Proc_1;
------------
-- Func_2 --
------------
function Func_2 (Self : Middle_T) return Boolean is
begin
return False;
end Func_2;
end Father.Middle;
-------------------------------
-- File: father-middle-lead.ads
-------------------------------
package Father.Middle.Leaf with SPARK_Mode => On is
pragma Elaborate_Body;
type Leaf_T is new Middle_T with null record;
function Create return Leaf_T;
overriding function Func_1 (Self : Leaf_T) return Boolean;
end Father.Middle.Leaf;
编译器出现以下错误:
父亲中间。ads:7:04:middle类型的第一个冰点必须出现在原始体“Proc_1”(SPARK RM 7.7(8))的早期调用区域内[L1]
中间父区。ads:7:04:区域从中间父区开始。adb:7[L2]
中间父区。ads:7:04:区域结束于中间父区。adb:7[L2]
父亲中。广告:7:04:第17行的第一个冰点[L3]
如果我在Father.Middle.Leaf而不是Father.Middle中重写Proc_1,那么错误就消失了
我读过书,但我是个新手
有没有一种方法可以覆盖父中的Proc_1
我使用的是Windows 10中的GNAT Studio Community 2020。不幸的是,我没有一个结论性的答案,但我确实怀疑早期的区域分析是否正确 我怀疑的原因是,如果您向继承自
Middle\T
的Father.Middle
添加一个新的具体类型Dummy\T
,那么突然间一切看起来都很好(如下所示)。在我看来(但我在这里可能是错的),添加这样一种类型不应改变Proc_1
的Middle_T
的早期区域分析结果;唯一的区别是,Middle\T
的凝固点从原始代码中的包装规格末尾移到下面代码中的Dummy\T
类型定义之前
此外,还不清楚为什么Father.Middle
正文中的Proc\u 1
的早期区域没有扩展到包规范中,因为pragmadetaily\u body
已在Father.Middle
中说明。似乎(如果我理解正确的话)早期区域分析器在Father.Middle
规范的正文开头或结尾的某个地方检测到一个不可预加工的构造。然而,那里似乎没有这样的东西。因此,在分析扩展代码时可能会出现一些错误,但这纯粹是猜测,因为早期的区域分析器没有提供任何跟踪其行为的信息。因此,很难从最终用户的角度检查分析器的推理
请再次注意,我作为终端用户的分析是假设性的。这个错误可能仍然是正确的,而我可能是错的。我只是觉得我的发现很有趣,可以分享
(GNAT参考文献:、分析仪和)
中间父亲。广告
package Father.Middle with SPARK_Mode is
pragma Elaborate_Body;
type Middle_T is abstract new Father_T with null record;
overriding procedure Proc_1 (Self : in out Middle_T; Another : Middle_T);
private
pragma SPARK_Mode (Off);
function Func_2 (Self : Middle_T) return Boolean;
--
-- ??? Just add a new concrete type and all is fine now?
--
type Dummy_T is new Middle_T with null record;
overriding function Func_1 (Self : Dummy_T) return Boolean is (False);
end Father.Middle;
你试过以下方法吗
type Middle_T is tagged;
overriding procedure Proc_1 (Self : in out Middle_T; Another : Middle_T);
type Middle_T is abstract new Father_T with null record;
或
有时,为了使用能够声明子程序的功能,向前声明类型会有所帮助。错误消息的单位和行是什么?感谢您的回复。我已经更新了这个问题。您需要覆盖所有抽象操作(
Proc\u 1
和Func\u 1
),以获得Father\u T
的任何具体扩展,例如Middle\u T
。由于您没有为Middle\t
重写Func\u 1
,因此您的代码有一个错误。验证程序在解释错误方面做得不是很好,但我怀疑编译器会这样做。但是中间部分被声明为抽象的。我错过什么了吗?谢谢。不,我是。我把Middle\T
误读为一个具体的扩展,对不起。谢谢你的回复!你是对的。错误现在消失了。我不知道发生了什么事。在接受此解决方案之前,我将等待几天,以查看是否发布了新的解决方案。再次感谢。
type Middle_T;
procedure Proc_1 (Self : in out Middle_T; Another : Middle_T);
type Middle_T is abstract new Father_T with null record;