On Mar 26, 7:26 am, I wrote:
> package Foo is
> type X is new Ada.Finalization.Controlled with
> record T : Trace ; end record ;
> Trace_Stash : Trace ;
> end Foo ;
> ...
> package body Foo is
> procedure Finalize( Object : in out X ) is begin
> Trace_Stash = Object.T ;
> Object.T.Trace_Finalize ;
> end ;
> procedure Adjust( Object : in out X ) is begin
> Object.T = Trace_Stash ;
> Object.T.Trace_Adjust ;
> end ;
> end Foo ;
OK, figuring out initialization was blindingly easy once I got the
right trick. Consider the following additional code in package Foo:
package Foo
[...]
type Nil is null record ;
function Construct_X( T : Trace ) return Nil ;
end Foo ;
....
package body Foo is
function Construct_X( T : Trace ) return Nil is begin
Trash_Stash = T ;
return Nonce : Nil ;
end ;
function Initialize( Object : in out X ) is begin
Object.T = Trace_Stash ;
Object.T.Trace_Initialize ;
end ;
end Foo ;
Why do I have a constructor function for X that returns Nil? Here's
the sample code:
declare
T : Trace ;
NA : Nil := Construct_X( T ) ;
A : X ;
begin
...
What happens is that the Nil constructor has a side effect upon a
package variable, which is then used in the default initialization of
variable A. The realization I needed was that I could use a trivial
constructor function within a declarative_part--where I would have
otherwise used a procedure--to get side effects by which default
initialization would work. That part of this trick is applicable in
other code.
My actual code is more involved. Here's an actual snippet, lifted
from a unit test:
[declarative_part]
NA : Nil := Construct_Traced_Existence( Name => "A", T => T ) ;
A : Traced_Existence ;
NB : Nil := Construct_Traced_Existence( Name => "B", T => T ) ;
B : Traced_Existence ;
[handled_sequence_of_statements]
A := B ;
The trace that comes back (it's generated at run-time) is "(A.I)(B.I)
(A.F)(A.A)", just like you'd expect. The previous method I had tried,
which used ordinary constructor functions, that one didn't work well
at all.
Eric


|