【问题标题】:"cannot generate code for file random.ads" when running a .adb program运行 .adb 程序时“无法为文件 random.ads 生成代码”
【发布时间】:2018-12-03 03:48:38
【问题描述】:

我在 Ada 中运行程序时遇到了一些麻烦。我有以下三个项目文件(我使用 GPS):

Types.ads

package types is
   subtype T_valeurind is Integer range 2..14;
   type T_couleur is (s, h, c, d);
   type t_carte is record
      valeur : T_valeurind;
      couleur : T_couleur;
   end record;

   type T_jeu is array (1..7) of t_carte;

   function trans(val: Character) return T_valeurind;

end types;

Trans.adb

with types;
use types;
WITH Text_Io , Ada.Integer_Text_Io;
USE Text_Io , Ada.Integer_Text_Io;


function trans(val : Character) 
   return T_valeurind is
   ret: Integer;
begin 
   case val is
     when '3' => ret:=3;
     when '4' => ret:=4;
     when '5' => ret:=5;
     when '6' => ret:=6;
     when '7' => ret:=7;
     when '8' => ret:=8;
     when '9' => ret:=9;
     when 'T' => ret:=10;
     when 'J' => ret:=11;
     when 'Q' => ret:=12;
     when 'K' => ret:=13;
     when 'A' => ret:=14;
     when others => null;
  end case;
  return ret;
end trans;

Test.adb

WITH Text_Io , Ada.Integer_Text_Io;
USE Text_Io , Ada.Integer_Text_Io;
with types;
use types;


procedure test is
begin
   put(T_valeurind'Image(trans('c')));
end test;

我只是想执行 test.adb 来检查我的函数“trans”是否运行良好。当我在 GPS 中构建文件时,一切正常。但是当我想运行它们时,我有以下消息,并且没有执行:

无法为文件 types.ads(包规范)生成代码

gprbuild: *** 编译阶段失败

[2018-12-02 02:01:39] 进程以状态 4 退出,100% (2/2),经过时间:01.65s

但令人不安的是,我第一次尝试运行代码时,它成功了。没有改变任何东西,它就停止了工作。 我不知道该怎么办。我看到这条消息只是告诉我 .ads 文件不可编译,但我尝试编译和运行的是 .adb 文件,所以我不明白.. 你知道为什么它不起作用吗?

提前谢谢大家!

【问题讨论】:

    标签: gps ada


    【解决方案1】:

    首先,这些不是项目文件,其类型为.gpr;它们是您项目中的 Ada 源文件。

    您的types.ads 承诺function trans,这意味着它需要types.adb 中的包体,

    package body types is
       function trans(val : Character) 
          return T_valeurind is
          ret: Integer;
       begin 
          case val is
            when '3' => ret:=3;
            when '4' => ret:=4;
            when '5' => ret:=5;
            when '6' => ret:=6;
            when '7' => ret:=7;
            when '8' => ret:=8;
            when '9' => ret:=9;
            when 'T' => ret:=10;
            when 'J' => ret:=11;
            when 'Q' => ret:=12;
            when 'K' => ret:=13;
            when 'A' => ret:=14;
            when others => null;
         end case;
         return ret;
       end trans;
    end types;
    

    (嗯。如果你传入一个无效字符,你将返回未初始化的数据,就像没有得到一个Constraint_ErrorT_valeurind 包含值 2,你不应该覆盖它吗?)

    您的 trans.adb 指定了一个库级函数。

    当我在 GPS 中构建文件时,一切正常。但是当我想运行它们时,我有以下消息,并且没有执行:

    如果一个包规范 (types.ads) 需要一个主体 (types.adb) 而您没有提供它,编译器将在您尝试编译它时产生您报告的消息。如果您尝试仅编译 test.adb 就可以了。如果您尝试build test.adb,它将尝试编译包 Types 并且会失败,无论您是尝试 Build 还是 Build & Run。

    我不知道第一次怎么会这样!

    【讨论】:

    • 如果我理解得很好,既然你说的是types.ADB,那我得创建这个文件来放你的代码,对吧?
    • 这就是我尝试过的,它看起来很有效。我现在还有其他问题,但是这个问题已经解决了。非常感谢!
    【解决方案2】:

    您似乎忘记在测试程序的上下文中包含您的function Trans。如果它不在上下文中,你就不能使用它。

    尝试添加:

    with Trans;
    

    procedure Test的上下文子句。

    【讨论】:

    • 好吧,我尝试使用 Trans 添加;在我的 test.adb 文件的开头,但它告诉我没有找到 trans.adb。然而 trans.adb 在同一个文件夹(src)中。我想我误解了一些关于函数及其声明的东西......
    • 这可能意味着找不到trans.ads(对于with一个单元,必须有一个规范,在.ads
    【解决方案3】:

    使用强大的 Ada 枚举功能(以及一些糟糕的输入处理策略,例如异常),您的整个问题一开始就可以避免。您的trans 程序将毫无用处。

    如果你对你的枚举值的顺序关系感兴趣,你也可以使用Ada的'First*(第一个枚举字面量),'Last(最后一个枚举文字),'Pos(枚举内的位置),'Succ(下一个枚举文字),'Pred(上一个枚举字面量)。

    如果您为变量执行内存映射,您可以使用 'Valid 来检查变量是否具有有效值,并省去对约束错误进行异常捕获的需要。

    请看下面的例子:

    with Ada.Text_IO; use Ada.Text_IO;
    with Ada.Exceptions; use Ada.Exceptions;
    
    procedure Hello is
        -- miwing chars and literal values in enum
        -- note that jack is 'J' and not the single source code character J
        type My_Awesome_Enum is ('1', '2', '3', 'J', Q, K, Ace);
        for My_Awesome_Enum use
           ('1' => -1,
           '2' => 2,
           '3' => 3,
           -- ...
           'J' => 11,
           Q => 12,
           K => 13,
           Ace => 14);
        temp : Integer;
        prev : My_Awesome_Enum;
        succ : My_Awesome_Enum;
        temp2 : My_Awesome_Enum;
    begin
        -- ------------------------------------------
        -- Ada enum power
        declare
        begin
          for value in My_Awesome_Enum loop
            temp := My_Awesome_Enum'Enum_Rep(value);
            Put_Line("Enum litteral value: " & value'Image & " - memory representation: " & Integer'Image(temp));
    
            if value /= My_Awesome_Enum'First then
                prev := My_Awesome_Enum'Pred(value);
                Put_Line("Previous: " & prev'Image);
            else
                Put_Line("No previous");
            end if;
            if value /= My_Awesome_Enum'Last then
                succ := My_Awesome_Enum'Succ(value);
                Put_Line("Next: " & succ'Image);
            else
                Put_Line("No next");
            end if;
            Put_Line("");
          end loop;
        end;
        -- ------------------------------------------
        -- conversion from some input source
        Put_Line("");
        declare
            strInput : String := "Unknown user value";
        begin
            Put_Line("Handling of user input: " & strInput);
            temp2 := My_Awesome_Enum'Value (strInput);
        exception
        when E: others =>
            Put_Line("Exception catched: " & Exception_Information (E));
            Put_Line("Setting value to Ace instead");
            temp2 := Ace;
        end;
        Put_Line("tmp2 value: " & temp2'Image & " - memory representation: " & Integer'Image(My_Awesome_Enum'Enum_Rep(temp2)));
        -- ------------------------------------------
        -- mmemory mapping
        Put_Line("");
        declare
            my_int : Integer := -3;
            mapped_Enum : My_Awesome_Enum;
            for mapped_Enum'Address use my_int'Address;
            last_enum : My_Awesome_Enum := (My_Awesome_Enum'Last);
            stop_condition : Integer := (last_enum'Enum_Rep) + 2;
        begin
            while (my_int < stop_condition) loop
                if mapped_Enum'Valid then
                    Put_Line("Enum with value: " & my_int'Image & " is valid.");
                else
                    Put_Line("Memory mapping would result in invalid enum for value: " & my_int'Image);
                end if;
                my_int := my_int + 1;
            end loop;
        end;
    
    end Hello;
    

    这会给出以下输出(https://www.tutorialspoint.com/compile_ada_online.php,使用 GNATMAKE v7.1.1):

    构建:

    $gnatmake -o hello *.adb
    gcc -c hello.adb
    gnatbind -x hello.ali
    gnatlink hello.ali -o hello
    

    执行:

    Enum litteral value: '1' - memory representation: -1
    No previous
    Next: '2'
    
    Enum litteral value: '2' - memory representation:  2
    Previous: '1'
    Next: '3'
    
    Enum litteral value: '3' - memory representation:  3
    Previous: '2'
    Next: 'J'
    
    Enum litteral value: 'J' - memory representation:  11
    Previous: '3'
    Next: Q
    
    Enum litteral value: Q - memory representation:  12
    Previous: J
    Next: K
    
    Enum litteral value: K - memory representation:  13
    Previous: Q
    Next: ACE
    
    Enum litteral value: ACE - memory representation:  14
    Previous: K
    No next
    
    Handling of user input: Unknown user value
    Exception catched: raised CONSTRAINT_ERROR : bad input for 'Value: "Unknown user value"
    
    Setting value to Ace instead
    tmp2 value: ACE - memory representation:  14
    
    Memory mapping would result in invalid enum for value: -3
    Memory mapping would result in invalid enum for value: -2
    Enum with value: -1 is valid.
    Memory mapping would result in invalid enum for value:  0
    Memory mapping would result in invalid enum for value:  1
    Enum with value:  2 is valid.
    Enum with value:  3 is valid.
    Memory mapping would result in invalid enum for value:  4
    Memory mapping would result in invalid enum for value:  5
    Memory mapping would result in invalid enum for value:  6
    Memory mapping would result in invalid enum for value:  7
    Memory mapping would result in invalid enum for value:  8
    Memory mapping would result in invalid enum for value:  9
    Memory mapping would result in invalid enum for value:  10
    Enum with value:  11 is valid.
    Enum with value:  12 is valid.
    Enum with value:  13 is valid.
    Enum with value:  14 is valid.
    Memory mapping would result in invalid enum for value:  15
    

    【讨论】:

    • 嗯,我是 Ada 的新手,所以我还不能理解你的所有代码,但我保留了它,因为我认为它以后会有用。非常感谢您的宝贵时间!
    • 基本上,Ada 提供了枚举从/到字符串的转换以及枚举内存表示的功能。它省去了编写和维护与您发布的类似的开关案例的痛苦。
    • 请注意,如果您自己不定义内存表示,编译器将自己定义一个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-07
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多