From: Dmitry A. Kazakov on
On Sun, 14 Feb 2010 06:20:32 -0800 (PST), Gautier write-only wrote:

> A question for the RM hermeneutists.
> The instruction marked below with ">>>" goes well through one Ada 95
> compiler (GNAT with -gnat95) but is not accepted by another one
> (ObjectAda 7.2.2).
> Which compiler is right ?
>
> procedure Init(
> xl : in out Excel_Out_Stream'Class;
> format : Excel_type:= Default_Excel_type
> )
> is
> dummy_xl_with_defaults: Excel_Out_File;
> begin
> -- Check if we are trying to re-use a half-finished object
> (ouch!):
> if xl.is_created and not xl.is_closed then
> raise Excel_Stream_Not_Closed;
> end if;
> dummy_xl_with_defaults.format:= format;
>>>> Excel_Out_Stream(xl):= Excel_Out_Stream(dummy_xl_with_defaults);
> end Init;
>
>>>> excel_out.adb: Error: line 595 col 5 LRM:3.9.3(8), The type of the target of an assignment shall not be abstract
>
> For those asking themselves what the *@#$! that code is doing, since
> the xl variable is already initialized, the purpose of the := is to re-
> initialize an object (xl) with the default values of the root type.
> Since the root type is abstract, I need a concrete derived object
> (dummy_xl_with_defaults) to get these default values. Subsidiary
> question: is there another way of doing that in one ':=' ?

package P is
type T is abstract tagged private;
procedure Reset (X : in out T'Class);
private
type Root is tagged record -- Non-abstract
I : Integer;
end record;
type T is abstract new Root with null record;
end P;

package body P is
Defaults : Root := (I => 123);

procedure Reset (X : in out T'Class) is
begin
Root (X) := Defaults;
end Reset;
end P;.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Adam Beneschan on
On Feb 14, 6:20 am, Gautier write-only <gautier_niou...(a)hotmail.com>
wrote:
> Hello,
>
> A question for the RM hermeneutists.
> The instruction marked below with ">>>" goes well through one Ada 95
> compiler (GNAT with -gnat95) but is not accepted by another one
> (ObjectAda 7.2.2).
> Which compiler is right ?
>
>   procedure Init(
>     xl        : in out Excel_Out_Stream'Class;
>     format    :        Excel_type:= Default_Excel_type
>   )
>   is
>     dummy_xl_with_defaults: Excel_Out_File;
>   begin
>     -- Check if we are trying to re-use a half-finished object
> (ouch!):
>     if xl.is_created and not xl.is_closed then
>       raise Excel_Stream_Not_Closed;
>     end if;
>     dummy_xl_with_defaults.format:= format;>>> Excel_Out_Stream(xl):= Excel_Out_Stream(dummy_xl_with_defaults);
>
>   end Init;
>
> >>> excel_out.adb: Error: line 595 col 5 LRM:3.9.3(8), The type of the target of an assignment shall not be abstract

This is indeed illegal, although offhand I'm not sure it should be.

-- Adam
From: Hibou57 (Yannick Duchêne) on
Le Mon, 15 Feb 2010 18:05:09 +0100, Adam Beneschan <adam(a)irvine.com> a
écrit:
>
> This is indeed illegal, although offhand I'm not sure it should be.
You cannot create an instance of an abstract type, initialized or not, so
assignment is unlikely to be legal. Whatever it is of instantiation or
assignment, this would not make no sense with an abstract type, as some
method would not be defined. Well, to be honest, one alternative could
have been to allow such a thing and simply disallow invocation of abstract
methods (Borland Turbo Pascal did this), but then, what about if the
object is passed as a class-wide parameter ? The method receiving the it
as a class-wide parameter may access an abstract method. Allowing
instantiation of abstracts and disallowing to pass it where class-wide is
expected, would not have been clean.

--
No-no, this isn't an oops ...or I hope (TM) - Don't blame me... I'm just
not lucky
From: Adam Beneschan on
On Feb 15, 9:05 am, Adam Beneschan <a...(a)irvine.com> wrote:

> > A question for the RM hermeneutists.
> > The instruction marked below with ">>>" goes well through one Ada 95
> > compiler (GNAT with -gnat95) but is not accepted by another one
> > (ObjectAda 7.2.2).
> > Which compiler is right ?
>
> >   procedure Init(
> >     xl        : in out Excel_Out_Stream'Class;
> >     format    :        Excel_type:= Default_Excel_type
> >   )
> >   is
> >     dummy_xl_with_defaults: Excel_Out_File;
> >   begin
> >     -- Check if we are trying to re-use a half-finished object
> > (ouch!):
> >     if xl.is_created and not xl.is_closed then
> >       raise Excel_Stream_Not_Closed;
> >     end if;
> >     dummy_xl_with_defaults.format:= format;>>> Excel_Out_Stream(xl):= Excel_Out_Stream(dummy_xl_with_defaults);
>
> >   end Init;
>
> > >>> excel_out.adb: Error: line 595 col 5 LRM:3.9.3(8), The type of the target of an assignment shall not be abstract
>
> This is indeed illegal, although offhand I'm not sure it should be.

FYI, I asked about this on Ada-Comment, and got a response from
Randy. Making this legal would be a problem, since there's a
possibility that the abstract type has an abstract Adjust routine. If
the assignment on the abstract view were allowed (even though it's an
abstract "view conversion" of an object with a concrete type), it
would be possible that a nonexistent Adjust routine would be called,
and that sort of thing is prohibited by the language.

On the other hand, it's probably a problem even if the type isn't
abstract. If you use a view conversion on the left side of an
assignment

T2(X) := <something>;

and T2 is a controlled type, and X's type is a type derived from T2,
then an Adjust will be called on just the "T2" portion of X but this
Adjust won't affect any other component of the type extension. IMHO,
there's a good chance that this will not produce the desired result.
The same is true if T2(X) is passed as an OUT or IN OUT parameter to
some procedure, and the procedure assigns to the parameter as a
whole. Unfortunately, it's probably too late to fix Ada to prevent
things like this, or to allow things like this in an abstract case.

My own recommendation: If you want the 14 components of the abstract
type Excel_Out_Stream to be treated as a unit, then make them a unit---
i.e. define a record type with 14 components, and then
Excel_Out_Stream would have just one component of that record type.
Of course, that decision probably has to be made when the package is
first written; making that change now would require changing how all
those components are accessed everywhere else in the program. Barring
that, you can either write 14 assignment statements and hope the
compiler is smart enough to optimize them, or you can use a "trick"
like Dmitry's suggestion, which will "work" but (in my opinion)
doesn't help set up a type structure that accurately reflects the
concepts in your program.

-- Adam

From: Adam Beneschan on
On Feb 16, 2:03 am, Gautier write-only <gautier_niou...(a)hotmail.com>
wrote:
> On 16 Feb., 01:59, Adam Beneschan <a...(a)irvine.com>:
>
> > FYI, I asked about this on Ada-Comment, and got a response from
> > Randy.  [...]
>
> Thanks!
> IHMO, no need to worry about how well or not the standard handles
> that.
> To answer my original question, can I conclude that GNAT is wrong on
> that case, and that I can send a report ?

Yes, if GNAT is accepting this, then it's wrong.

-- Adam