Ada_Ru форум

Обсуждение языка Ада

Странность с испо льзованием GENERIC

Оставить новое сообщение

Сообщения

cs_a994
Странность с испо льзованием GENERIC
2014-06-19 20:27:53
Hello!

Компилятор не может подставить соответсвующую процедуру GET. Вместо 

   procedure Get
     (From : String;
      Item : out Num;
      Last : out Positive);

из Ada.Text_IO.Decimal_IO или Ada.Text_IO.Integer_IO пытается подставить 

   procedure Get
     (Item  : out Num;
      Width : Field := 0);

, т.е. не видит процедуры ввода из строки и пытается пользоваться вводом из файла, что,
естественно, вызывает ошибку:

        200:16 expected private type "Ada.Text_Io.File_Type"
        200:16 found type "Standard.String"
        200:10 no candidate interpretations match the actuals:
        200:10 too many arguments in call to "GET"
        197:13 expected private type "Ada.Text_Io.File_Type"
        197:38 expected type "RECORD_TIMES" defined at line 40
        200:68 expected type "RECORD_TIMES" defined at line 40
        197:13 found type "Standard.String"
        197:7 no candidate interpretations match the actuals:
        197:7 too many arguments in call to "GET"

Фрагмент текста ( звёздочкой помечена строка 197 из протокола ):

   type RECORD_TIMES is delta 0.001 digits 13 ;

   package IIO is new TEXT_IO.INTEGER_IO ( INTEGER ) ;
      use IIO ;

   package DIO is new TEXT_IO.DECIMAL_IO ( RECORD_TIMES ) ;
      use DIO ;

   generic
      type COMPONENTS is private ;
   procedure GET_PAIR_G
      ( DATA             : in STRING ;
        SEPARATOR        : in STRING ;
        START , DURATION : in out COMPONENTS ) ;

   procedure GET_PAIR_G
      ( DATA             : in STRING ;
        SEPARATOR        : in STRING ;
        START , DURATION : in out COMPONENTS ) is
   -- Tries to split the input string into two parts separated by SEPARATOR
   -- If there is no first part propagates the exception raised by the GET
   -- If there is no second part raises TRUNCATED_DATA_ERROR

      LAST_POS : INTEGER := INDEX ( DATA , SEPARATOR , 1 ) ;

   begin -- GET_PAIR_G

*     GET ( DATA ( 1 .. LAST_POS ) , START , LAST_POS ) ;

      begin
         GET ( DATA ( LAST_POS + SEPARATOR'LENGTH .. DATA'LAST ) , DURATION , LAST_POS ) ;
      exception
         when Ada.IO_EXCEPTIONS.END_ERROR => raise TRUNCATED_DATA_ERROR ;
      end ;
   end GET_PAIR_G ;

 
Vasiliy Fofanov
Re: [ada_ru] Странность с использованием GENERIC
2014-06-20 11:22:57
> Компилятор не может подставить соответсвующую процедуру GET.

Потому что ее - соответствующей - не существует. Вам непонятно что - где ошибка (а вернее -
ошибкИ), или почему такая диагностика? Тот факт, что ваша программа неверна, вам понятен, или нет?

cs_a994
Re: [ada_ru] Стран ность с ис п ользова н ием GENERIC
2014-06-22 23:09:25
Как это не существует? А в пакете Ada.Text_IO.Fixed_IO в строке 73 что ( помечена звёздочкой )?
Аналоги есть и в Ada.Text_IO.INTEGER_IO, и в Ada.Text_IO.DECIMAL_IO.

Или при объявлении GENERIC'ов нельзя использовать другие GENERIC-модули ( пакеты, процедуры )? Или
нужно их как-то по-другому описывать?

------------------------------------------------------------------------------
--                                                                          --
--                         GNAT RUN-TIME COMPONENTS                         --
--                                                                          --
--                 A D A . T E X T _ I O . F I X E D _ I O                  --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--          Copyright (C) 1992-2009, Free Software Foundation, Inc.         --
--                                                                          --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
-- apply solely to the  contents of the part following the private keyword. --
--                                                                          --
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                          --
-- You should have received a copy of the GNU General Public License and    --
-- a copy of the GCC Runtime Library Exception along with this program;     --
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
-- <http://www.gnu.org/licenses/>.                                          --
--                                                                          --
-- GNAT was originally developed  by the GNAT team at  New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
--                                                                          --
------------------------------------------------------------------------------

--  In Ada 95, the package Ada.Text_IO.Fixed_IO is a subpackage of Text_IO.
--  This is for compatibility with Ada 83. In GNAT we make it a child package
--  to avoid loading the necessary code if Fixed_IO is not instantiated. See
--  routine Rtsfind.Text_IO_Kludge for a description of how we patch up the
--  difference in semantics so that it is invisible to the Ada programmer.

private generic
   type Num is delta <>;

package Ada.Text_IO.Fixed_IO is

   Default_Fore : Field := Num'Fore;
   Default_Aft  : Field := Num'Aft;
   Default_Exp  : Field := 0;

   procedure Get
     (File  : File_Type;
      Item  : out Num;
      Width : Field := 0);

   procedure Get
     (Item  : out Num;
      Width : Field := 0);

   procedure Put
     (File : File_Type;
      Item : Num;
      Fore : Field := Default_Fore;
      Aft  : Field := Default_Aft;
      Exp  : Field := Default_Exp);

   procedure Put
     (Item : Num;
      Fore : Field := Default_Fore;
      Aft  : Field := Default_Aft;
      Exp  : Field := Default_Exp);

*   procedure Get
     (From : String;
      Item : out Num;
      Last : out Positive);

   procedure Put
     (To   : out String;
      Item : Num;
      Aft  : Field := Default_Aft;
      Exp  : Field := Default_Exp);

private
   pragma Inline (Get);
   pragma Inline (Put);

end Ada.Text_IO.Fixed_IO;
cs_a994
Re: [ada_ru] Стран ность с ис п ользова н ием GENERIC
2014-06-22 23:15:50
А в пакете ADA.TEXT_IO.FIXED _ IO в строке 73 что ( помечена звёздочкой )?

Мне непонятно, почему компилятор не видит именно эту процедуру. В чём ошибочность моей программы?
При объявлении GENERIC'ов нельзя использовать другие GENERIC-пакеты? Или надо на них как-то
по-другому ссылаться?

------------------------------------------------------------------------------
--                                                                          --
--                         GNAT RUN-TIME COMPONENTS                         --
--                                                                          --
--                 A D A . T E X T _ I O . F I X E D _ I O                  --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--          Copyright (C) 1992-2009, Free Software Foundation, Inc.         --
--                                                                          --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
-- apply solely to the  contents of the part following the private keyword. --
--                                                                          --
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                          --
-- You should have received a copy of the GNU General Public License and    --
-- a copy of the GCC Runtime Library Exception along with this program;     --
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
-- <http://www.gnu.org/licenses/>.                                          --
--                                                                          --
-- GNAT was originally developed  by the GNAT team at  New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
--                                                                          --
------------------------------------------------------------------------------

--  In Ada 95, the package Ada.Text_IO.Fixed_IO is a subpackage of Text_IO.
--  This is for compatibility with Ada 83. In GNAT we make it a child package
--  to avoid loading the necessary code if Fixed_IO is not instantiated. See
--  routine Rtsfind.Text_IO_Kludge for a description of how we patch up the
--  difference in semantics so that it is invisible to the Ada programmer.

private generic
   type Num is delta <>;

package Ada.Text_IO.Fixed_IO is

   Default_Fore : Field := Num'Fore;
   Default_Aft  : Field := Num'Aft;
   Default_Exp  : Field := 0;

   procedure Get
     (File  : File_Type;
      Item  : out Num;
      Width : Field := 0);

   procedure Get
     (Item  : out Num;
      Width : Field := 0);

   procedure Put
     (File : File_Type;
      Item : Num;
      Fore : Field := Default_Fore;
      Aft  : Field := Default_Aft;
      Exp  : Field := Default_Exp);

   procedure Put
     (Item : Num;
      Fore : Field := Default_Fore;
      Aft  : Field := Default_Aft;
      Exp  : Field := Default_Exp);

*   procedure Get
     (From : String;
      Item : out Num;
      Last : out Positive);

   procedure Put
     (To   : out String;
      Item : Num;
      Aft  : Field := Default_Aft;
      Exp  : Field := Default_Exp);

private
   pragma Inline (Get);
   pragma Inline (Put);

end Ada.Text_IO.Fixed_IO;
Vasiliy Fofanov
Re: [ada_ru] Странность с использованием GENERIC
2014-06-23 13:42:30
Гм. Из вашего вопроса я заключаю, что вам непонятно, почему ваша программа неверна :)

> Как это не существует? А в пакете Ada.Text_IO.Fixed_IO в строке 73 что ( помечена звёздочкой )?
Аналоги есть и в Ada.Text_IO.INTEGER_IO, и в Ada.Text_IO.DECIMAL_IO.

Ну вот, всего этого и не существует :) Настраиваемые пакеты - это не реальный код, это просто
шаблоны. Чтобы в реальности появились соответствующие процедуры - их вначале надо настроить.

> Или при объявлении GENERIC'ов нельзя использовать другие GENERIC-модули ( пакеты, процедуры )?
Или нужно их как-то по-другому описывать?

Напрямую - нельзя разумеется. Просто задумайтесь, как будет выглядеть конечный результат? Что мы
будем вызывать в итоге? Ближайшее к искомому, что язык предоставляет - это т.наз. формальные
пакеты. См. руководство языка, глава 12.7. Вот что-то такого рода:

with Ada.Containers.Ordered_Maps;
generic
   with package Mapping_1 is new Ada.Containers.Ordered_Maps(<>);
package Ordered_Join is

... и т.д.


Но это просто объявление обязательств программиста, настраивать пакет нужно будет все равно.
Например то объявление, что выше, подразумевает, что вы где-то в программе настроите пакет
Ada.Containers.Ordered_Maps, и передадите его в качестве параметра.

Не знаю - тот ли это механизм, что вы ищете, или нет?

Vasiliy Fofanov
Re: [ada_ru] Странность с использованием GENERIC
2014-06-23 15:58:22
> Что это шаблоны и их надо настраивать я знаю. И в моей программе они настроены и даже работают.
!-)
> 
>    type RECORD_TIMES is delta 0.001 digits 13 ;
> 
>    package IIO is new TEXT_IO.INTEGER_IO ( INTEGER ) ;
>       use IIO ;
> 
>    package DIO is new TEXT_IO.DECIMAL_IO ( RECORD_TIMES ) ;
>       use DIO ;

Это хорошо, но это только полдела :)

> Так при соотвествующей настройке моей процедуры должен выбираться соответствующий настроенный
пакет ввода/вывода и подставляться.

Ну а с какой стати компилятор отождествит профиль

GET (STRING, INTEGER, COMPONENTS)

с профилем

GET (STRING, INTEGER, INTEGER) ?

Во-первых вы объявили COMPONENTS как тип PRIVATE, то есть иными словами никакой совместимости с
целочисленным типом не предусматривается (и вообще не предусматривается никаких знаний о внутренней
структуре типа). Если совместимость нужна - необходимо объявить формальный параметр целочисленного
типа -

    type COMPONENTS is range <>;

Во-вторых, даже и в этом случае не стоит забывать о строгой типизации языка Ада. С точки зрения
языка тип COMPONENTS это одно, а INTEGER это другое, два несовместимых типа. Требуется явное
преобразование:

    GET ( DATA ( 1 .. LAST_POS ) , START , INTEGER (LAST_POS) ) ; 

Вот тогда должно начать компилироваться... :)

> Или я слишком много хочу от компилятора?

Ну вобщем да - вы хотите, чтобы компилятор компилировал неправильные программы ;)

cs_a994
Re: [ada_ru] Стран ность с ис п ользова н ием GENERIC
2014-06-23 20:56:33
В любом случае компилятор ( вернее, уже сборщик ) ведёт себя странно.

Если просто откомпилировать ( без сборки ) программу, то ошибок нет. Ошибки возникают при сборке.

По-хорошему должено было бы выдаваться сообщение о невозможности именно _подстановки типов_, а не о
несоответствии профиля вызова. Поскольку, исходя из диагностики, считается возможной подстановка
типа в _другую_ процедуру GET и в качестве ошибки выдаётся несоответсвие количества аргументов.

С другой стороны, может, я, конечно, и здесь ошибаюсь, GENERIC'и по своей сути есть макросредство,
порождающее копии кода с указанными подстановками. Соответственно, при рекурсивной подстановке
корректность описания может ( и должна ) быть проверена так сказать "задом наперёд", т.е. от более
конкретных модулей к более абстрактным, от того, что я описываю в своей программе к описаным ранее.
При имеющихся описаниях на этапе настройки моей процедуры GET_PAIR все типы определены и профили
вызова полностью определены. Следовательно, корректная подстановка возможна.

Но, похоже, работаёт это не так, что и вызвало недоумение.
Vasiliy Fofanov
Re: [ada_ru] Странность с использованием GENERIC
2014-06-24 12:42:40
> В любом случае компилятор ( вернее, уже сборщик ) ведёт себя странно.
> 
> Если просто откомпилировать ( без сборки ) программу, то ошибок нет. Ошибки возникают при сборке.

Нет, ничего подобного. Сообщения

...
200:16 expected private type "Ada.Text_Io.File_Type"
200:16 found type "Standard.String"
...

и т.п. - это сообщения периода компиляции, а не периода сборки.

> По-хорошему должено было бы выдаваться сообщение

Такого рода пожелания существуют столько же времени, сколько существуют синтаксические ошибки в
программах. На самом деле компилятор может на каждую ошибку просто говорить "syntax error", всё что
дополнительно - это не более чем бонус. Восстановление после синтаксической ошибки - это совсем не
простое дело, и не всегда возможно. А уж тем более не всегда возможно догадаться, что хотел
программист. Я лично при невозможности статического связывания на догадки компилятора относительно
того, "что бы это могло быть" вообще почти никогда не смотрю, поскольку в отличие от компилятора,
точно знаю, что там ДОЛЖНО быть, и этого знания (и знания языка) мне достаточно, чтобы исправить
ошибку ;)

> Но, похоже, работаёт это не так, что и вызвало недоумение. 

Да, работает это не так. Домысливать не стоит, лучше писать программы в соответствии с требованиями
Руководства на язык :)

cs_a994
Re: [ada_ru] Стран ность с ис п ользова н ием GENERIC
2014-07-01 23:10:37
>> Если просто откомпилировать ( без сборки ) программу, то ошибок нет. Ошибки возникают при сборке.
 > Нет, ничего подобного. Сообщения 

Да, действительно. В GPS "Check synax" и "Compile file" разные действия. !-)

>> Но, похоже, работает это не так, что и вызвало недоумение. 
> Да, работает это не так. Домысливать не стоит, лучше писать программы в соответствии с
требованиями Руководства на язык :)

Из LRM это не очень очевидно ( то есть надо внимательно поползать по нему, чем я давно не занимался
). Собственно, от шаблона я ждал немного другого.

Что нужно было получить? Единообразную обработку для пар целых чисел ( INTEGER ) и чисел с
фиксированной точкой ( decimal fixed point ), ну и принципе для любых типов чисел. ( В процессе
уточнения задачи оказалось, что обработка всё-таки не единообразна, но это к обсуждению уже не
отностится )

Моя задача решается немного по-другому. И это тоже не работает:

> Ближайшее к искомому, что язык предоставляет - это т.наз. формальные пакеты. См. руководство
языка, глава 12.7.

В данном случае не поможет точно по той же причине, по которой не проходит изначально предложенный
мной вариант -- нельзя подствить впрямую _любой_ тип или пакет в качестве формального параметра
настройки GENERIC'а, которые будут реально сопоставлены  друг другу в теле создаваемого пакета. Но
это сопставление ( в моём случае ) можно сделать в окружении пакета.

LRM в этой части ещё внимательно почитаю и поэкспериментирую с этим. Может, найду ещё какой-нибудь
путь.

Спасибо.

Привожу работающий модельный фрагмент программы для нужного мне случая.

   type BYTE is new INTEGER range 0 .. 255 ;
      for BYTE'SIZE use 8 ;

   type RECORD_TIMES is delta 0.001 digits 13 ;


   package IIO is new TEXT_IO.INTEGER_IO ( INTEGER ) ;
      use IIO ;

   package BIO is new TEXT_IO.INTEGER_IO ( BYTE ) ;
      use BIO ;

   package DIO is new TEXT_IO.DECIMAL_IO ( RECORD_TIMES ) ;
      use DIO ;


   A        : INTEGER := 0 ;
   B        : BYTE := 0 ;
   C        : RECORD_TIMES := 0.0 ;


   generic
      type COMPONENTS is private ;

      with procedure GET
         ( SRC : in STRING ;
           DST : out COMPONENTS ;
           POS : out POSITIVE ) ;

   procedure GET_ITEM_G
      ( DATA             : in STRING ;
        ITEM             : out COMPONENTS ) ;

   procedure GET_ITEM_G
      ( DATA             : in STRING ;
        ITEM             : out COMPONENTS ) is

      LAST_POS : POSITIVE := 1 ;

   begin -- GET_ITEM_G

      GET ( DATA , ITEM , LAST_POS ) ;

   end GET_ITEM_G ;


   procedure GET_ITEM  is new  GET_ITEM_G ( INTEGER , IIO.GET ) ;
   procedure GET_ITEM  is new  GET_ITEM_G ( BYTE , BIO.GET ) ;
   procedure GET_ITEM  is new  GET_ITEM_G ( RECORD_TIMES , DIO.GET ) ;
Vasiliy Fofanov
Re: [ada_ru] Стран ность с ис пользован ием GENERIC
2014-07-02 14:18:11
> Да, действительно. В GPS "Check synax" и "Compile file" разные действия. !-)

Это и логично: синтактический анализ не подразумевает генерации объектного кода. Соответственно, с
одной стороны, возможна обработка исходных текстов, для которых невозможно сгенерировать объектный
код (generic, spec, separate), с другой - отсутствует анализ ошибок, связанных с отображением типов
данных на целевую машину и т.п.

> Из LRM это не очень очевидно (

Мне трудновато судить, поскольку я по нему практически обучался грамоте, но верю :) В любом случае,
рад слышать что вам удалось отыскать подходящее решение.

Новое сообщение:
Страницы: 1

Чтобы оставить новое сообщение необходимо Зарегистрироваться и Войти