From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.5-pre1 (2020-06-20) on ip-172-31-74-118.ec2.internal X-Spam-Level: X-Spam-Status: No, score=-1.9 required=3.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.5-pre1 Date: 28 Jan 93 15:25:46 GMT From: stt@spock.camb.inmet.com (Tucker Taft) Subject: Re: private types and recompilation Message-ID: <1993Jan28.152546.25758@inmet.camb.inmet.com> List-Id: In article <9301271722.aa25516@Paris.ics.uci.edu> kanderso@mabillon.ICS.UCI.EDU (Kenneth Anderson) writes: >In comp.lang.ada you write: > >>When Ada 83 was designed, why did the designers choose to put >>the details of private types in package specifications, rather than >>in package bodies (which is more in the spirit of information hiding, and >>better supports independent compilation). > >I'm not sure, but I think because the compiler needs to know the size >of the types so that it can allocate space for parameters in the >subprograms that are defined in the spec. Parameters are not a great problem, because they can in general be passed by reference (though if the full type is a scalar or access type, pass by copy is required). However, to be able to allocate local variables of a private type outside the defining package, and to implement the "=" operator and ":=" operation correctly, some knowledge of the representation is required. It is possible to defer all of this to link-time, but for languages like Ada (and C++, by the way), the choice was made in favor of minimizing run-time overhead, at the expense of more recompilation. A general principle in Ada is that every abstraction has a "logical interface" (the visible part), a "physical interface" (the private part), and an "implementation" (the body). If you don't change the logical interface, then you don't have to edit the source of the clients. If you don't change the physical interface, then you don't have to recompile the clients; only relink. This principle of separation is carried out quite consistently throughout the language, and has been maintained (and somewhat enhanced with private child packages) in Ada 9X. As far as the official rationale, here is a paragraph from the '86 Rationale for the Design of the Ada Programming Language (section 9.3.3 "Influence of Separate Compilation on the Design of Packages," page 183): The declaration of a private type therefore does not in itself provide enough information for storage allocation and other operations. The full declaration of the type is needed, and so is any representation clause that the user wants: storage allocation will therefore require the information provided by the private part. Note that placing this information in the package body would not be satisfactory since it would create unnecessary dependences of other compilation units on this body, with the consequence that changes in the algorithms provided in the body would require recompilation of these other compilation units, even in the absence of change to the full type declaration. As a relatively late change to Ada 83, the rules for "incomplete" types were relaxed somewhat, so that if a private type was in fact an access type, then the full definition of its designated type could be deferred into the package body, as mentioned in the response by Ken Anderson: >>generic >> type ATOM is private; >>package LIST_ADT is >> type POSITION is private; >> type LIST is private; >> procedure CREATE(L: in out LIST); >> procedure INSERT_AFTER(L: in out LIST; P: POSITION; A: ATOM); >> ... > >>private >> type LIST; >> type POSITION is access LIST; > >You only need the previous two lines. The declaration below can be >hidden in the body of the package. > >> type LIST is record >> A: ATOM; >> NEXT: POSITION; >> end record; >>end LIST_ADT; > > >>-Dave Erickson > >Ken By the way, in Ada 9X, there is another alternative, namely an "abstract tagged type." Such a type (say, "T") can be used as the root of a hierarchy of (tagged) types, and the corresponding "class-wide type" (T'CLASS) can be used as the type of a subprogram formal parameter, allowing algorithms to be written that have no knowledge of the reprsentation of the various derivatives of the abstract type. Such "class-wide" algorithms work by relying strictly on the "primitive" operations of the abstract type. Parameters of a class-wide type are naturally passed by reference, and calls on the primitive operations of such a type are dynamically bound to the appropriate operation, based on a "tag" that identifies the specific type of the actual object associated with the given formal parameter. It is interesting to note that the '86 Rationale foreshadowed this capability (quoting from earlier in section 9.3.3): ... A more flexible architecture -- evolved perhaps from today's "tagged architectures" -- would indeed allow data representation choices to be deferred until link time, or even later. S. Tucker Taft stt@inmet.com Ada 9X Mapping/Revision Team Intermetrics, Inc. Cambridge, MA 02138