From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00,FORGED_GMAIL_RCVD, FREEMAIL_FROM autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,efc9f994d31d0d5e,start X-Google-Attributes: gid103376,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!postnews.google.com!s19g2000prg.googlegroups.com!not-for-mail From: Eric Hughes Newsgroups: comp.lang.ada Subject: Limited initialization for non-limited types Date: Wed, 26 Mar 2008 06:26:42 -0700 (PDT) Organization: http://groups.google.com Message-ID: NNTP-Posting-Host: 166.70.57.218 Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Trace: posting.google.com 1206538002 2550 127.0.0.1 (26 Mar 2008 13:26:42 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Wed, 26 Mar 2008 13:26:42 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: s19g2000prg.googlegroups.com; posting-host=166.70.57.218; posting-account=5RIiTwoAAACt_Eu87gmPAJMoMTeMz-rn User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12,gzip(gfe),gzip(gfe) Xref: g2news1.google.com comp.lang.ada:20578 Date: 2008-03-26T06:26:42-07:00 List-Id: 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