在 Ada 中使用归约表达式时范围检查失败

问题描述 投票:0回答:1

我尝试将函数

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
ada
1个回答
0
投票

我不确定这是一个错误。这可能是对 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 是否需要实现者来执行此操作。

© www.soinside.com 2019 - 2024. All rights reserved.