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: 22 Oct 92 22:19:17 GMT From: dog.ee.lbl.gov!hellgate.utah.edu!caen!zaphod.mps.ohio-state.edu!darwin.su ra.net!paladin.american.edu!news.univie.ac.at!hp4at!mcsun!ub4b!cfmu!news@ucbvax .Berkeley.EDU (Stef Van Vlierberghe) Subject: Re: User-defined assignment Message-ID: <1992Oct22.221917.15169@cfmu.eurocontrol.be> List-Id: > So the question is how much Ada implementor expense and effort is > justified relative to the benefits of the additional friendliness and > flexibility. I believe that the real cost is the danger of people falling for the cheap-but-unsafe solution of non-limited non-finalized types, rather than going for the elaborate-but-sound approach (it happens!). The second-best problem is the one with generics. Of the thousands (or more ?) generic Abstract Data Type packages (lists, rings, queues, stacks, maps, etc... ) Very few have limited formal types, perhaps inspired by Booch's approach in Software Components with Ada. In Ada9X we expect to get an automatically finalized type X, but if we also want a list of X's, ring of X's, etc... we need to convert the generics to use procedure a limited private generic formal type and generic formal function "=" and procedure ASSIGN, or build the composite abstraction ad-hoc. Then there is a lot of minor problems, that still affect programmers emotionally. They are bound to get "restless" when they are expected to write tons of code such as : procedure ASSIGN ( TO : in out T; VALUE : in T ) is begin COMP1.ASSIGN ( TO.COMP1, VALUE.COMP1 ); COMP2.ASSIGN ( TO.COMP2, VALUE.COMP2 ); end; function "=" ( LEFT, RIGHT : T ) return BOOLEAN is begin return COMP1."=" ( LEFT.COMP1, RIGHT.COMP1 ) and then COMP2."=" ( LEFT.COMP2, RIGHT.COMP2 ); end; Some constructs are not so easy to replace, e.g. an array aggregate can't be replaced by a construction function. And finally, in the process of going to limited-ness some might still be surprised by the "Midas touch" of limitedness (if a type is derived from it, contains it, or is completed by it, it becomes limited too). They could get desperate when they see the effect disturb much more of an application than they initially thought. I can't imagine that all this would cost less than implementing some modest form of user-defined assignment, and this for several reasons : I believe that the feature is implementable at a fairly early stage in a compiler, with an appropriate intermediate representation, it could stay entirely in the compiler's front-end. After all, most of the code to be generated can be represented in straight Ada, some of it relies on frames in expression contexts and local frames that don't interfere with the visibility rules. Expecting no more than 50 compiler front-ends for 9X, that justifies the cost. There are many restrictions one could put on user-defined assignment that are simplifying the implementation and are much less of a nuisance to the programmer than the absence of the feature. One of the more obvious ones is supporting only record types. This protects the predefined language environment (there are no predefined record types), prevents the problems with discriminants (that can't be record types), except for function return, they can always be passed by reference, etc... The nuisance for the programmer is that private types that were completed with non-records have to be put inside a record type, as one would do when needing a default value in Ada83. Finally there are cases where user-defined assignment actually makes compiler implementation simpler. A recently published Language Study Note (LSN-1043) discusses the function return of local self-referential objects (e.g. objects with access discriminants that point to themselves, the Ada9X solution to "mix-in"). With user-defined assignment, it becomes the application programmer's responsibility to implement a proper copy, resetting the self-reference of the copy to itself. Then the compiler can call it to implement a "normal" function return. Without it, compilers would need to do fancy tricks with the stack, delaying the normal stack-pop at function return until the time the enclosing context has done with the function result. Alternatively, you can't return such local objects, and we add one more case of "if you use language-feature X, then you (and your clients) lose language feature Y". As these "unmovable" types currently have no specific language category, this restriction may well affect any (inherently) limited types, including "movable" inherently limited types, such as (again) finalized types. -- Stef VAN VLIERBERGHE Eurocontrol - Central Flow Management Unit stef@cfmu.eurocontrol.be Avenue des Arts 19H Tel: +32 2 729 33 42 B-1040 BRUSSELS Fax: +32 2 729 32 16 Belgium