!standard 4.3.1 05-02-07 AI95-00413/01 !class amendment 05-02-07 !status No Action (10-0-0) 05-02-12 !status work item 05-02-07 !status received 05-02-07 !priority Medium !difficulty Medium !subject Partial view, task, and protected aggregates !summary A distinct syntax is proposed for aggregates used to define the value of a task type, protected type, or partial view. If "others => <>" is ultimately supported at all for non-array aggregates, it would only apply to visible non-discriminant components. On a somewhat separate issue, in an aggregate with a task part, or a function call that returns an object with a task part, any task parts are not activated until after the outermost enclosing composite object is fully and successfully initialized. !problem AI 389 proposes that partial view aggregates be supported. It borrows the "others => <>" notation to cover hidden components. However, there are significant maintenance issues associated with using "others" in a non-array aggregate, and it seems unfortunate to tie support for partial view aggregates to the use of others. Furthermore, whether or not to require "others=>" for aggregates defining a value of a task or protected type is debatable. On a separate issue, it is not clearly specified when a task that is part of an object defined by an aggregate or a function call is activated. !proposal A distinct syntax for aggregates is proposed which makes it clear when they are being used to define a value of a partial view, task, or protected type. Here are examples that illustrate the syntax: (private and A, B, C=>D) (task and Disc => True) (protected) (private) The syntax "(private)" may be used as the value for any partial view with no visible components, including those whose full type might be non-composite. In a partial view aggregate, only nonlimited components may have a value specified by an expression; (visible) limited components shall be specified to have the value "<>". In the evaluation of a partial view aggregate for a controlled type with a non-null Initialize procedure, the discriminants, if any, are first assigned, then the remainder of the object is default initialized, the Initialize procedure is invoked, and finally the non-discriminant components with a specified value are assigned. This ensures that the Initialize procedure sees a value that it could normally see during default initialization. For aggregates of a partial view without a non-null Initialize procedure, the components with specified values are assigned, and then the remainder of the components are default initialized. We also propose private extension aggregates: (X with private) (Y with private and B, C=>D) The word "private" must appear in an extension aggregate if the type of the extension aggregate is derived from the type of the ancestor part through one or more extension parts and any of them are private. If the type of the ancestor part is limited, it shall be specified by a subtype_mark rather than an expression. Simlarly, if a visible component not inherited from the ancestor part is limited, it shall be specified as "<>". In a private extension aggregate for a partial view of a controlled type with a non-null Initialize procedure, the discriminants are determined, the remainder of the object is default initialized, the Initialize procedure is invoked, and then the components or ancestor part specified by expressions (rather than "<>" or a subtype_mark) are assigned. In a private extension aggregate for a partial view without a non-null Initialize procedure, the ancestor expression, if any, and the components with values specified by an expression, are assigned, and then the remainder of the object is default initialized. The legality of an aggregate, and in particular whether it is for a partial view, and what components are visible, is determined at the point where the aggregate appears. The legality of the aggregate is not rechecked in an instance. For tasks that are part of an aggregate, or that are part of an object defined by a function call, we propose to defer activating the task until the outermost composite object containing the task is fully and successfully initialized. This ensures that the task will not refer to potentially uninitialized parts of the enclosing object via a discriminant of an access type. !wording TBD, depending on whether intent of proposal is approved. !discussion By providing a distinct syntax for these non-record aggregates, we eliminate a number of unpleasant issues. For example, the syntax "(private)" has no implication that there are any components at all, whereas "(others => <>)" does imply that, which is jarring if the full type turns out to be non-composite. As mentioned in the !problem, by eliminating the need to use "others" simply to handle potentially hidden components, we allow it to be reserved for cases where the user intentionally wants to forego full coverage checking. Finally, because the syntax is specifically designed for partial views, it makes sense even in a generic, where in the instance a full view might be available. By not requiring that the legality of the aggregate be rechecked in the instance, we allow it to work in any generic with a (definite or discriminated) formal private type. In general, the rules should be simpler, because we have no need to restrict a partial view aggregate to types which are certain to have a full/actual type that is composite. Once we adopt the use of the term "private" for partial view aggregates, it is natural to adopt the use of "task" and "protected" for aggregates producing values of such types. We chose to use "and" to separate the reserved word ("private", "task", or "protected") from the list of specified components, because "with" was already in use for specifying extension aggregates. Other possibilities considered and rejected were: 1) (task Disc=>True) -- drop the "and" 2) (private with A,B,C) -- use "with" instead of "and" (private X with A,B,C) -- and sneak the ancestor part before -- the "with" if an extension aggregate -- (but then it sounds like "X" is private -- rather than some or all other components, -- and "(private X with null record)" is a loser) 3) (Disk=>True and task) -- put the reserved word at the end (X with A, B and private) -- (seems potentially harder to parse -- since "and" is a legal binary operator) 4) (Disk=>True in task) -- use "in" rather than "and" (X with A, B in private) -- (also harder to parse since "in" is legal within an expression) !example (See discussion.) --!corrigendum 02.09(2) !ACATS test !appendix From: Tucker Taft Sent: Monday, February 7, 2005 4:32 PM Here is my second-to-last AI before the meeting, on issues relating to aggregates of a partial view, task, or protected type. I also suggest a rule for when a task is activated that is part of an object defined by an aggregate or a function call. I did *not* propose wording for this, because it seems so speculative, and deserves at least a vote on intent in Paris to justify the effort. [This is version /01 of the AI - ED] ************************************************************* From: Erhard Ploedereder Sent: Tuesday, February 8, 2005 12:10 PM My comments on Tuck's as yet unnumbered AI: 1. The RM still lacks a rule for determining the master of the tasks created by partial view aggregates. 2. With the re-established coverage rules in this AI, why is it necessary at all to keyword the situation? I.e., rather than (private and A,B,C => D) why not (A,B,C => D) and a semantic rule that says that missing components are default initialized (presuming that the visible components all have been checked as present in the aggregate). This would do away with extra syntax (and discussions thereof). It has only one minor(?) flaw, if one considers it as a flaw: () becomes a valid aggregate. (I say, so what. Hardly worse than (private). Parsing issues? not really. Generics issues? possibly. ) What am I missing? 3. Ceterum censeo in anticipation of actual wording: all this cannot possibly be presented under a syntax called record_aggregate. But we could globally rename to composite_aggregate. Not perfect because of the arrays, but definitely better than record_*. 4. We should air the issue on whether we want aggregates for non-private task and protected types. ************************************************************* From: Tucker Taft Sent: Tuesday, February 8, 2005 2:05 PM > My comments on Tuck's as yet unnumbered AI: I think Randy posted it as AI-416 [AI-413, actually - ED] > 1. The RM still lacks a rule for determining the master of the tasks > created by partial view aggregates. Are you implying that it would be different than that for a "full view" aggregate? I believe AI-162 was intended to specify masters of all sorts of things. > 2. With the re-established coverage rules in this AI, why is it necessary > at all to keyword the situation? I.e., > rather than > (private and A,B,C => D) > why not > (A,B,C => D) and a semantic rule that says that missing components > are default initialized (presuming that the visible components all > have been checked as present in the aggregate). I think this could be quite misleading, and it introduces the issue that you have more or fewer components depending on where the aggregate is, which could create real maintenance headaches or mysteries. At least with "private" you know that when you move the aggregate into a place that has a full view, you need to replace "private" with the specification of the previously hidden components. > This would do away with extra syntax (and discussions thereof). It has > only one minor(?) flaw, if one considers it as a flaw: > () becomes a valid aggregate. (I say, so what. Hardly worse than > (private). Parsing issues? not really. Generics issues? possibly. ) > > What am I missing? I would rather not have partial view aggregates at all, than to simply say you ignore the private components. More importantly, there is some real subtlety about what happens with controlled types, in particular, when and if the "Initialize" procedure is invoked for an aggregate. The AI I wrote indicates that if there is a "private," then Initialize will be invoked. We know that if there is not private, as with current aggregates, Initialize is *not* invoked for the aggregate. I think the presence of "private" or something like it is important to make this significant distinction. (I realize I didn't emphasize this in the AI, and I'm sorry. But figuring out how to handle the Initialize procedure was by far the hardest part of getting the semantics right, and in fact drove the decision to disallow specifying expressions for limited components in a partial view aggregate.) > 3. Ceterum censeo in anticipation of actual wording: > all this cannot possibly be presented under a > syntax called record_aggregate. But we could globally rename > to composite_aggregate. Not perfect because of the arrays, but > definitely better than record_*. Perhaps "Other aggregates" as the name of the section, and "other_aggregate" as the syntactic category. > 4. We should air the issue on whether we want aggregates for non-private > task and protected types. I think if we have partial view aggregates of a limited type, then we should have task and protected type aggregates as well. But I am willing to forego all three. *************************************************************