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 ;

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

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

Как это не существует? А в пакете 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;

А в пакете 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;

Гм. Из вашего вопроса я заключаю, что вам непонятно, почему ваша программа неверна :)

Как это не существует? А в пакете 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, и передадите его в качестве параметра.

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

Что это шаблоны и их надо настраивать я знаю. И в моей программе они настроены и даже работают. !-)

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) ) ;

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

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

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

В любом случае компилятор ( вернее, уже сборщик ) ведёт себя странно.

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

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

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

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

В любом случае компилятор ( вернее, уже сборщик ) ведёт себя странно.

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

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

...

200:16 expected private type "Ada.Text_Io.File_Type"

200:16 found type "Standard.String"

...

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

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

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

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

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

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

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

Да, действительно. В 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 ) ;

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

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

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

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

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

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