comp.lang.ada
 help / color / mirror / Atom feed
* Limited initialization for non-limited types
@ 2008-03-26 13:26 Eric Hughes
  2008-03-26 14:02 ` Robert A Duff
                   ` (5 more replies)
  0 siblings, 6 replies; 15+ messages in thread
From: Eric Hughes @ 2008-03-26 13:26 UTC (permalink / raw)


Is there any way of getting in-place initialization for non-limited
objects?  This would be similar to that for limited types as specified
in ARM05/7.5(8.1/2).

Unfortunately, this is not a hypothetical question.  I'm writing a
test object used within the unit tests a certain package.  The test
object is instrumented for white-box testing; it contains a trace
object as a component.  I want to trace the three events of
Ada.Finalization.Controlled.  The trace object is associated with the
variable itself, not with any value that the variable might contain.
Ordinarily, assignment would overwrite the trace object.  Actually, it
still does.  I save and restore the trace object in the Finalize and
Adjust procedures:

    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.  I'll just admit up front that this is a little Evil(TM).  With
this technique, you can get most of the effect of overriding the
assignment operator.  And this implementation doesn't work with
multiple tasks unless you have task-specific storage.  That said, I'm
essentially recreating part of a debugger capability--to attach a
monitor to the value of a variable and observe it.  This sort of white-
box testing has pretty much kept me out of debuggers entirely for a
while now.  And even though it's far from efficient, I'm using it only
in a test environment, not in a production one.  So I won't stop using
this approach.

So here's the problem.  I can't trace the Initialize call
"correctly".  Consider the obvious initialization:

    T : Trace ;
    A : X := Construct_X( T ) ;

Because X is not a limited type, this code translates thus (in one
ordering):

    T : Trace ;
    A : X ;
    Initialize( A ) ;
    Temp : X := Construct_X( T ) ; -- as if limited, constructed in
place
    Initialize( Temp ) ;
    Finalize( A ) ;
    A := Temp ;
    Adjust( A ) ;
    Finalize( Temp ) ;

The first thing that doesn't work is that A gets the wrong trace
object.  After the call to Adjust, variable A has the same default
trace object it started with.  The temporary had the specified object
T and it's lost.

And it gets worse.  When Initialize is called on A, A has the default
trace object, not T.  The only way to trace the initialization is to
use the default trace object.  That's what I'll be doing (barring
another approach), but I don't like it.  I'm adding a procedure to set
Trash_Stash and will use that during Initialize.

While I have an immediate work-around, I'm writing this in advance of
a next round of language debate.  There are a number of ideas that
come to mind in thinking about alternate ways of dealing with this
problem.

1) Limited-style initialization for non-limited types.  Here's example
syntax:

    A : X := limited Construct_X( T ) ;

The translation would be thus:

    A : X := Construct_X( T ) ; -- as if X were a limited type
    Initialize( A ) ;

It's much more efficient to boot.  Personally, I'd prefer this were
the default, but there are backward-compatibility issues to consider.
I'd also add the following syntax to enforce creation of a temporary:

    A : X := not limited Construct_X( T ) ;


2) Variable-specific record components.  Consider this:

    type X is new Ada.Finalization.Controlled with
        record
            -- value components (ordinary)
        private
            -- variable components (persistent)
            T : Trace ;
        end record ;

The idea is that components in the private section are simply not
copied under assignment.

In addition to the kind of testing application I'm doing, I can think
of another important application for this: dynamic binding.  The big
winner in this space has been Java reflection.  I don't like that
interface as written because it exposes everything and is an endless
source of mischief.  But Java reflection has been instrumental in
creating dynamic binding systems that have become so popular in web
applications.  Substitute "N : Name" as a private component in the
example and you have a key technical hook in the language that allows
a dynamic binding system to be known to be safe and correct.


3) Anonymous limited types.  I don't see any particular reason why the
semantics couldn't be worked out for the following declaration:

    B : limited Any_Type := Initial_Value_Function ;

The ARM is littered with references to phrases such as "the limited
view of a type".  What are the semantic difficulties with this?  For
single declarations they seem to be modest.  Isn't this almost the
same as an in-but-not-out parameter to a procedure?


4) Derived limited types.  The ARM states (roughly) that a limited
type must derive from limited types.  But what about a type that is
explicitly a limited view of a possibly not-limited type?

    type C is overriding limited new Any_Type ;

Access through type C would be limited.  Access through another
available mechanism might not be limited.


Eric



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

end of thread, other threads:[~2008-04-02  4:06 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-03-26 13:26 Limited initialization for non-limited types Eric Hughes
2008-03-26 14:02 ` Robert A Duff
2008-03-27  0:07   ` Eric Hughes
2008-03-26 15:08 ` Dmitry A. Kazakov
2008-03-26 22:13 ` Randy Brukardt
2008-03-27  3:25   ` Eric Hughes
2008-03-28  6:56     ` Randy Brukardt
2008-03-28 15:25       ` Eric Hughes
2008-03-28 21:53         ` Randy Brukardt
2008-03-28 23:37           ` Eric Hughes
2008-04-02  3:00         ` Eric Hughes
2008-03-26 23:00 ` Lucretia
2008-03-28 11:23 ` Martin Krischik
2008-03-28 15:47   ` Eric Hughes
2008-04-02  4:06 ` Eric Hughes

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