stt@ada-uts.UUCP (01/01/86)
Just to get a little meaty technical discussion going... Here are some proposals for Ada '88, arising from our use of Ada in building compilers, database managers, etc: 1) Support user-defined finalization for packages and limited types. 2) Support user-defined assignment for limited types. 3) Extend identifier visibility rules to eliminate need for most "use" clauses. I consider (1) essential to using Ada for significant systems programming, anytime multi-access or multi-tasking exists in the program or the environment (to guarantee files are closed, buffers are flushed, locks are released, storage is reclaimed, etc.) (2) is mostly a syntactic sugar issue, though any language supporting the notion of abstract types ought to support it. (3) is probably necessary for the upward-compatible implementation of (2), to give correct visibility characteristics to user-defined ":=". One mechanism for implementing (1) would be as follows: The "begin" of a declarative part would be extended as follows: [ when end => STATEMENT_LIST ] begin The statement_list would be executed when the declarative part is exited for any reason, after waiting for any tasks to complete. Exceptions raised and not handled in the statement list would cause the statement_list to be terminated, and the original exiting action to continue. In addition, a finalization procedure may be defined for a limited type, with the following syntax: procedure "end"(OBJ: in out LIM_TYPE) is begin ... end "end"; When such a procedure is visible (see discussion of (3) below), then in addition to waiting for tasks to terminate, a block statement, subprogram body, or task is not finished until each of the dependent objects are finalized (by calling "end" on them). Any exceptions raised and not handled by the "end" procedure cause the procedure to return and processing continues with the next "end" procedure. For limited objects designated by access values, the "end" procedure may be executed once no references remain, prior to reclamation of the storage, but after termination of all task components of the object. Let me be the first to say that the proposed syntax is pretty ugly, but user-defined finalization is so important that in the absence of more creative suggestions, this would still be worthwhile. The implementation of (2) is pretty straightforward, stealing all the rules from user-defined "=", except that the subprogram spec must be of the form: procedure ":="(L : in out LIM_TYPE; R : in LIM_TYPE) is begin ... end ":="; Restricting this to limited types is to eliminate confusion with the many implicit assignments implied in legal operations on non-limited types (e.g. aggregates, array assignment, etc.). These are the same as the arguments for user-defined "=" being restricted to limited types (with the same holes in the arguments, presumably). The problem with (2) is that built-in ":=" is "directly" visible even when other implicitly defined operations (like "=") are not. To avoid forcing everybody to "use" the defining package of a limited type to get visibility on ":=" (or the horrendous pkg.":="(a, b)), we come to: The implementation for (3): Add a third place to search for identifiers after consulting "direct" visibility and "use" visibility -- "defining-package" visibility. Defining-package visibility would mean that after consulting the "use"d packages, each package in which the type of a parameter is defined is consulted for a subprogram/operator definition. Note that the package of the result-type is NOT included. In fact, if more than one package is represented among the types of the parameters, then it is guaranteed that at most one of them could have visibility to all of the parameter types, and hence only one of them could possibly provide a definition for the subprogram/operator. For example: x+y Assume type of x is pkg_x.type_x and type of y is pkg_y.type_y and pkg_y looks like this: with pkg_x; package pkg_y is type type_y is new integer; function "+"(a:pkg_x.type_x; b:type_y) return type_y; end pkg_y Then it should not be necessary to "use" pkg_y for Ada semantics to resolve "+" in x+y. This should eliminate most of the need for "use" clauses. All of these ideas are half-baked, but we still have 2 years to finish the baking... Tucker Taft Intermetrics, Inc. 733 Concord Ave Cambridge, MA 02138 (617) 661-1840
creedy@cca.UUCP (Christopher Reedy) (01/02/86)
In article <> stt@ada-uts.UUCP writes: >Here are some proposals for Ada '88, arising from >our use of Ada in building compilers, database managers, etc: > > 1) Support user-defined finalization for > packages and limited types. > 2) Support user-defined assignment for limited types. > 3) Extend identifier visibility rules to eliminate need > for most "use" clauses. . . . >One mechanism for implementing (1) would be as follows: . . . > >Let me be the first to say that the proposed syntax is pretty >ugly, . . . (Let me be the first to agree with you :-) Actually, I like this idea. However, I think you left out support for user defined initialization for limited types. Without this it does not seem possible to determine when an object is uninitialized except for the case of access variables, where the compiler supplies a default initialization. (See comment to #2 below.) > >The implementation of (2) is pretty straightforward, stealing all >the rules from user-defined "=", except that the subprogram spec must be >of the form: > procedure ":="(L : in out LIM_TYPE; R : in LIM_TYPE) is ^^^^^^ > begin ... end ":="; Interesting choice. I would have thought that the proper form of the argument is "out", not "in out". The semantics of "in out" would seem to require that the object be initialized prior to invoking the procedure. This isn't possible if the assignment is specifically intended to initialize the object. This usage might be feasible if there is a defined initialization (compiler or user) for objects of type LIM_TYPE. > >The implementation for (3): >Add a third place to search for identifiers after consulting >"direct" visibility and "use" visibility -- "defining-package" >visibility. . . . I also like this idea. However, in keeping with the general philosophy of Ada that "hidden" defaults should not be a source of confusion to the programmer and maintainer, it would seem that something like a limited form of USE that makes the operator symbols visible without making the entire package visible would be more appropriate. Chris Reedy
stt@ada-uts.UUCP (01/03/86)
Initialization may be specified for limited types which are record types, by supplying default expressions for the components. By nesting any type within a record (possibly discriminated), it is possible to specify a relatively arbitrary initialization. For example: type lim(x : integer) is limited private; ... type lim(x : integer) is record contents : exciting_type(x) := complicated_function(x); end record;
bmac3@ssc-bee.UUCP (Scott Pilet) (01/09/86)
> 3) Extend identifier visibility rules to eliminate need > for most "use" clauses. > > (3) is probably necessary for the upward-compatible > implementation of (2), to give correct visibility > characteristics to user-defined ":=". > > The problem with (2) is that built-in ":=" is "directly" visible > even when other implicitly defined operations (like "=") are not. > To avoid forcing everybody to "use" the defining package > of a limited type to get visibility on ":=" (or the horrendous > pkg.":="(a, b)), we come to: > > The implementation for (3): > Add a third place to search for identifiers after consulting > "direct" visibility and "use" visibility -- "defining-package" > visibility. Defining-package visibility would mean that > after consulting the "use"d packages, each package in which > the type of a parameter is defined is consulted for a subprogram/operator > definition. Note that the package of the result-type is NOT included. > > In fact, if more than one package is represented among the types > of the parameters, then it is guaranteed that at most one > of them could have visibility to all of the parameter types, > and hence only one of them could possibly provide a definition > for the subprogram/operator. > > For example: > x+y Assume type of x is pkg_x.type_x and type of y is pkg_y.type_y > and pkg_y looks like this: > > with pkg_x; > package pkg_y is > type type_y is new integer; > function "+"(a:pkg_x.type_x; b:type_y) return type_y; > end pkg_y > > Then it should not be necessary to "use" pkg_y for Ada semantics > to resolve "+" in x+y. > This should eliminate most of the need for "use" clauses. > > All of these ideas are half-baked, but we still have 2 years > to finish the baking... > > Tucker Taft > Intermetrics, Inc. > 733 Concord Ave > Cambridge, MA 02138 (617) 661-1840 In a large system effort, some other programmer may have a package with a y and a "+" that would allow x+y. The lack of a "use" statement adds to the complexity for debugging and sets the system up for a disaster in the future. The existence of a "use" statement may be nice for small Ada programs, but in a large project the use of it may add to the confusion. "with"ing and "rename"ing ensures that the software engineer is positive of where an identifier is from and what it is. More errors will be detected by the software tools used by the engineers in a large software project following this type of methodology. As a tool to aid the software engineer, a compiler message suggesting some resolution of an undefined identifier, operator, or procedure (etc.) is helpful, but a compiler allowing ambiguities that are technologically preventable can be disaster. scott pilet --these statements are my own and not Boeing's