我尝试将函数
A
中的数组串联转换为新的 Ada 2022 约简表达式(请参阅函数 B
),但出现 range check failed
错误。我做错了什么?
with Ada.Text_IO;
with Ada.Unchecked_Conversion;
with Interfaces;
procedure Learn is
type u8 is new Interfaces.Unsigned_8;
type u32 is new Interfaces.Unsigned_32;
type Bytes is array (Positive range <>) of aliased u8;
type Words is array (Positive range <>) of aliased u32;
Some_Words : Words (1 .. 3) := [1111, 22222, 333333];
subtype Bytes_4 is Bytes (1 .. 4);
function Convert is new Ada.Unchecked_Conversion (u32, Bytes_4);
function A (W : Words) return Bytes is
(Convert (W (1)) & Convert (W (2)) & Convert (W (3)));
A1 : Bytes := A (Some_Words);
function B (W : Words) return Bytes is
([for X of W => Convert (X)]'Reduce ("&", []));
B1 : Bytes := B (Some_Words);
begin
Ada.Text_IO.Put_Line (A1'Image);
Ada.Text_IO.Put_Line (B1'Image);
end Learn;
控制台输出:
$ gprbuild -q -P main.gpr
learn.adb:22:30: warning: too many elements for subtype of "Bytes" defined at line 22 [enabled by default]
learn.adb:22:30: warning: expected 0 elements; found 4 elements [enabled by default]
learn.adb:22:30: warning: Constraint_Error will be raised at run time [enabled by default]
Build completed successfully.
$ ./learn
raised CONSTRAINT_ERROR : learn.adb:22 range check failed
exit status: 1
我不确定这是一个错误。这可能是对 ARM 的(过于?)简单的解释。
learn.adacore 关于约简表达式的部分说,稍微向下一点,
A := [2, 3, 4];
I := A'Reduce ("+", 0);
相当于
I := 0;
for E of A loop
I := I + E;
end loop;
并且您可以看到,在您的情况下,您将累加器(相当于上面的
I
的局部变量)初始化为[]
,固定长度为0。
确实,使用
-gnatG
开关,我们得到
function b (w : words) return bytes is
begin
null;
return
do
[subtype T14b is bytes (1 .. 0)]
B37b : T14b := [];
L39b : for C40b in w'first(1) .. w'last(1) loop
[constraint_error when
not (integer(C40b) in w'first .. w'last)
"index check failed"]
x : u32 renames w (C40b);
B37b := [constraint_error "range check failed"];
end loop L39b;
in B37b end
....
end learn__b;
(
B37b
是累加器,赋值会产生无条件CE)。
ARM 在 ARM 4.5.10(24) 中表示“对该属性的使用进行评估...将归约表达式的累加器初始化为...初始值”。到目前为止,一切都很好(或很糟糕,取决于您的观点)。
下一段说“value_sequence的每个值都按顺序作为第二个(Value)参数传递给Reducer调用,第一个(Accumulator)参数是累加器的先前值,保存结果作为累加器的新值”。我认为当所需的结果类型不受约束时,您需要使用递归,并且我非常怀疑 ARG 是否需要实现者来执行此操作。