comp.lang.ada
 help / color / mirror / Atom feed
* controlled initialization
@ 2002-12-16  7:04 Maxim Reznik
  2002-12-16 14:33 ` Hyman Rosen
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Maxim Reznik @ 2002-12-16  7:04 UTC (permalink / raw)


Hi!
Can you help me?
I'm stuck with following example.

I expected statement
  return Statement'(Ada.Finalization.Controlled with C => 0);
created object of type Statement,
then Initialyze procedure would be called for it and
Put_Line printed "Init".

But when I compile program with GNAT 3.15p for Linux
it doesn't happen.

May be it's bug of GNAT?

Thank you

Maxim Reznik

------------------------------------
with Ada.Finalization;
package Tests is

    type Statement is new Ada.Finalization.Controlled with record
       C : Integer;
    end record;

    procedure Initialize (Item : in out Statement);

    subtype Class is Ada.Finalization.Controlled'Class;

    function Create_Statement return Class;

end Tests;

------------------------------------
with Ada.Text_IO;
package body Tests is

    procedure Initialize (Item : in out Statement) is
    begin
       Ada.Text_IO.Put_Line ("Init");
    end Initialize;

    function Create_Statement return Class is
    begin
       return Statement'(Ada.Finalization.Controlled with C => 0);
    end Create_Statement;

end Tests;

------------------------------------
with Tests;
procedure Test is

    use Tests;

    Object : Class := Create_Statement;
begin
    null;
end Test;




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: controlled initialization
  2002-12-16  7:04 controlled initialization Maxim Reznik
@ 2002-12-16 14:33 ` Hyman Rosen
  2002-12-16 15:06   ` Robert A Duff
                     ` (2 more replies)
  2002-12-16 23:31 ` Stephen Leake
  2002-12-16 23:31 ` Matthew Heaney
  2 siblings, 3 replies; 11+ messages in thread
From: Hyman Rosen @ 2002-12-16 14:33 UTC (permalink / raw)


Maxim Reznik wrote:

> I expected statement
>  return Statement'(Ada.Finalization.Controlled with C => 0);
> created object of type Statement,
> then Initialyze procedure would be called for it and
> Put_Line printed "Init".
>
> But when I compile program with GNAT 3.15p for Linux
> it doesn't happen.
>
> May be it's bug of GNAT?


Ooh, ooh, I know, I know! I remember this from a thread
a while ago. Init isn't called for objects that are
initialized by aggregates. A rationale is that since
you are supplying all the fields in the aggregate, you
can just do whatever setup the Init proccedure would
have done. Of course, this doesn't work if the Init
procedure has side effects. In that case, I think the
solution is to make the type limited, so that users can't
initialize with aggregates at all, and you can call the
Init procedure "by hand" in the private code.




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: controlled initialization
  2002-12-16 14:33 ` Hyman Rosen
@ 2002-12-16 15:06   ` Robert A Duff
  2002-12-16 23:26   ` Matthew Heaney
  2002-12-17  6:59   ` Maxim Reznik
  2 siblings, 0 replies; 11+ messages in thread
From: Robert A Duff @ 2002-12-16 15:06 UTC (permalink / raw)


Hyman Rosen <hyrosen@mail.com> writes:

>...In that case, I think the
> solution is to make the type limited, so that users can't
> initialize with aggregates at all, and you can call the
> Init procedure "by hand" in the private code.

You don't need to make it limited.  Just make it private.
Then aggregates can only appear inside the abstraction itself.
If the package body can write upon record fields, then there's
no point in forbidding it to use aggregates.

See also AI-287.

- Bob



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: controlled initialization
  2002-12-16 14:33 ` Hyman Rosen
  2002-12-16 15:06   ` Robert A Duff
@ 2002-12-16 23:26   ` Matthew Heaney
  2002-12-17  1:50     ` Hyman Rosen
  2002-12-17  6:59   ` Maxim Reznik
  2 siblings, 1 reply; 11+ messages in thread
From: Matthew Heaney @ 2002-12-16 23:26 UTC (permalink / raw)


Hyman Rosen <hyrosen@mail.com> wrote in message news:<1040049195.294541@master.nyc.kbcfp.com>...
> 
> Ooh, ooh, I know, I know! I remember this from a thread
> a while ago. Init isn't called for objects that are
> initialized by aggregates. A rationale is that since
> you are supplying all the fields in the aggregate, you
> can just do whatever setup the Init proccedure would
> have done.

The real problem is when you're declaring a deferred constant, e.g.

package P is

   type T is private;

   O : constant T;

private

   type T is new Controlled with null record;

   procedure Initialize (O : in out T);

   O : constant T := (Controlled with null record);

end P;

The problem is that the body of P hasn't elaborated at the moment when
object O is elaborated.  Were Initialize to be called at the point of
elaboration of O, then Program_Error would be raised because the body
of Initialize hasn't been elaborated yet.

So for aggregate initialization, Initialize doesn't get called, and
all initialization is done in-place.



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: controlled initialization
  2002-12-16  7:04 controlled initialization Maxim Reznik
  2002-12-16 14:33 ` Hyman Rosen
@ 2002-12-16 23:31 ` Stephen Leake
  2002-12-16 23:31 ` Matthew Heaney
  2 siblings, 0 replies; 11+ messages in thread
From: Stephen Leake @ 2002-12-16 23:31 UTC (permalink / raw)


Maxim Reznik <max1@mbank.com.ua> writes:

If you add a Put_Line in Create_Statement, you'll see that does get
called. 

Apparently this is one of those times when the compiler gets to
optimize out the call to Initialize, because Create_Statement is
supposed to return a fully initialized object.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: controlled initialization
  2002-12-16  7:04 controlled initialization Maxim Reznik
  2002-12-16 14:33 ` Hyman Rosen
  2002-12-16 23:31 ` Stephen Leake
@ 2002-12-16 23:31 ` Matthew Heaney
  2 siblings, 0 replies; 11+ messages in thread
From: Matthew Heaney @ 2002-12-16 23:31 UTC (permalink / raw)


Maxim Reznik <max1@mbank.com.ua> wrote in message news:<3DFD7B15.9050800@mbank.com.ua>...
> 
> I expected statement
>   return Statement'(Ada.Finalization.Controlled with C => 0);
> created object of type Statement,
> then Initialyze procedure would be called for it and
> Put_Line printed "Init".
> 
> May be it's bug of GNAT?

No, there is no bug.

> with Ada.Finalization;
> package Tests is
> 
>     type Statement is new Ada.Finalization.Controlled with record
>        C : Integer;
>     end record;
> 
>     procedure Initialize (Item : in out Statement);
> 
>     subtype Class is Ada.Finalization.Controlled'Class;
> 
>     function Create_Statement return Class;
> 
> end Tests;

In general, you should hide the fact of derivation from Controlled in
the private part of the spec, like this:

package Tests is

   type Statement_Type is private;

...
private

   type Statement_Type is new Controlled with record
     C : Integer;
   end record;

   procedure Initialize (Statement : in out Statement_Type);
...
end Tests;

Here, the partial view of the type can be tagged or non-tagged.  In my
example above, I have chosen not to make the partial view non-tagged.



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: controlled initialization
  2002-12-16 23:26   ` Matthew Heaney
@ 2002-12-17  1:50     ` Hyman Rosen
  2002-12-17  2:00       ` Bill Findlay
  2002-12-17  7:55       ` Simon Wright
  0 siblings, 2 replies; 11+ messages in thread
From: Hyman Rosen @ 2002-12-17  1:50 UTC (permalink / raw)


Matthew Heaney wrote:
>    O : constant T := (Controlled with null record);
> 
> The problem is that the body of P hasn't elaborated at the moment when
> object O is elaborated.  Were Initialize to be called at the point of
> elaboration of O, then Program_Error would be raised because the body
> of Initialize hasn't been elaborated yet.

Interesting. So (remembering that I don't know Ada) the following
would be illegal as well? If it is, is there a way to do what the
code obviously intends? Do I understand the issue correctly, that
is that MakeT could use O?

package P is
   type T is private;
   O : constant T;
private
   type T is new Controlled with null record;
   function MakeT return T;
   O : constant T := MakeT;
end P;




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: controlled initialization
  2002-12-17  1:50     ` Hyman Rosen
@ 2002-12-17  2:00       ` Bill Findlay
  2002-12-17  7:55       ` Simon Wright
  1 sibling, 0 replies; 11+ messages in thread
From: Bill Findlay @ 2002-12-17  2:00 UTC (permalink / raw)


On 17/12/02 01:50, in article DpvL9.30910$4W1.11730@nwrddc02.gnilink.net,
"Hyman Rosen" <hyrosen@mail.com> wrote:


> 
> Interesting. So (remembering that I don't know Ada) the following
> would be illegal as well? If it is, is there a way to do what the
> code obviously intends? Do I understand the issue correctly, that
> is that MakeT could use O?
> 
> package P is
>  type T is private;
>  O : constant T;
> private
>  type T is new Controlled with null record;
>  function MakeT return T;
>  O : constant T := MakeT;
> end P;
> 

We don�t need O to be deferred, or T to derive from Controlled,
for that sort of construction to fail, unfortunately.

All that's necessary is to call a function defined in the body of P
during the elaboration of P's spec.

This makes hiding the manufacture of exported ADT constants somewhat
problematic.

-- 
Bill-Findlay chez blue-yonder.co.uk ("-" => "")




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: controlled initialization
@ 2002-12-17  6:20 Grein, Christoph
  0 siblings, 0 replies; 11+ messages in thread
From: Grein, Christoph @ 2002-12-17  6:20 UTC (permalink / raw)


> Interesting. So (remembering that I don't know Ada) the following
> would be illegal as well? If it is, is there a way to do what the
> code obviously intends? Do I understand the issue correctly, that
> is that MakeT could use O?
> 
> package P is
>    type T is private;
>    O : constant T;
> private
>    type T is new Controlled with null record;
>    function MakeT return T;
>    O : constant T := MakeT;
> end P;

Absolutely correct, MakeT is not elaborated when you call it here. So this code is not illegal, but will raise an exception.

And why would you want to call a function here? A record initialisation can 
easily be used because you have full visibility of all components.

In a contrived case like the following, you would have a point. But then simply 
define your complicated function in a child package, use an Elaborate_Body 
pragma and call the function to initilise O. Here you are - no problem.

package P is
   type T is private;
   O : constant T;
private
   type T is new Controlled with record
     Comp: Some_Type;
   end record;
   O : constant T := (Controlled with Comp => Some very complicated code here);
end P;



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: controlled initialization
  2002-12-16 14:33 ` Hyman Rosen
  2002-12-16 15:06   ` Robert A Duff
  2002-12-16 23:26   ` Matthew Heaney
@ 2002-12-17  6:59   ` Maxim Reznik
  2 siblings, 0 replies; 11+ messages in thread
From: Maxim Reznik @ 2002-12-17  6:59 UTC (permalink / raw)


Hyman Rosen wrote:
> Maxim Reznik wrote:
> 
>>
>> May be it's bug of GNAT?
Silly me.

> 
> Ooh, ooh, I know, I know! I remember this from a thread
> a while ago. Init isn't called for objects that are
> initialized by aggregates. A rationale is that since
[skip]

Thank you very much. Now I see.
I appreciate everybody's answers.
I see how much I have still to learn in Ada.

Maxim Reznik




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: controlled initialization
  2002-12-17  1:50     ` Hyman Rosen
  2002-12-17  2:00       ` Bill Findlay
@ 2002-12-17  7:55       ` Simon Wright
  1 sibling, 0 replies; 11+ messages in thread
From: Simon Wright @ 2002-12-17  7:55 UTC (permalink / raw)


Hyman Rosen <hyrosen@mail.com> writes:

> Interesting. So (remembering that I don't know Ada) the following
> would be illegal as well? If it is, is there a way to do what the
> code obviously intends? Do I understand the issue correctly, that
> is that MakeT could use O?
> 
> package P is
>    type T is private;
>    O : constant T;
> private
>    type T is new Controlled with null record;
>    function MakeT return T;
>    O : constant T := MakeT;
> end P;

One possibility is to make O a function (inlined if you need to).

A related difficulty is where T is indefinite: from the under-work
Booch Components,

1   type Unconstrained_Map
2     (Number_Of_Buckets : Positive) is new Abstract_Map with private;
3
4   subtype Map is Unconstrained_Map (Number_Of_Buckets => Buckets);
5
6   function Null_Container return Unconstrained_Map;
7   --  Note, this function has to be provided but the object returned
8   --  is in fact a Map (ie, it is constrained).

Buckets in line 4 is a generic parameter, retained for consistency
with previous releases, specifying the default number of hash
buckets. Null_Container at line 6 is required because it's abstract in
the parent. Still, folk relying on Null_Container can use it with the
previous semantics.



^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2002-12-17  7:55 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-12-16  7:04 controlled initialization Maxim Reznik
2002-12-16 14:33 ` Hyman Rosen
2002-12-16 15:06   ` Robert A Duff
2002-12-16 23:26   ` Matthew Heaney
2002-12-17  1:50     ` Hyman Rosen
2002-12-17  2:00       ` Bill Findlay
2002-12-17  7:55       ` Simon Wright
2002-12-17  6:59   ` Maxim Reznik
2002-12-16 23:31 ` Stephen Leake
2002-12-16 23:31 ` Matthew Heaney
  -- strict thread matches above, loose matches on Subject: below --
2002-12-17  6:20 Grein, Christoph

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox