!standard 12.07 (03) 04-06-10 AI95-00317/07 !standard 12.07 (05) !standard 12.07 (10) !class amendment !status work item 04-06-07 !status Amendment 200Y 03-10-23 !status WG9 Approved 03-12-12 !status ARG Approved 8-0-2 03-10-04 !status work item 02-10-06 !status received 02-10-06 !priority Medium !difficulty Easy !subject Partial Parameter Lists for Formal Packages !summary A formal package may have a partially specified set of actual parameters. !problem When a generic has more than one formal package parameter, it is often important to link the two packages via their actuals. However, the only way to link the packages is to specify one with no actuals, and specify the other with all of its actuals. For example: generic with package Inst1 is new Gen1(<>); with package Inst2 is new Gen2(Inst1.A, Inst1.B, ...); ... package GP is ... The problem is that there may be some actuals of the second formal package which are *not* linked to the first one. The only way to deal with this is to add more formal parameters to the generic GP to specify the values for the remaining actual parameters. For example: generic type T1 is private; type T2 is private; with package Inst1 is new Gen1(<>); with package Inst2 is new Gen2(Inst1.A, Inst2.B, FT3 => T1, FT4 => T2); ... package GP is ... Unfortunately, this approach defeats much of the advantage of formal package parameters, which is to reduce the number of formals and simplify the usage of a generic. !proposal A formal package parameter may specify some, but not all, of its actual parameters. For example: generic with package Inst1 is new Gen1(<>); with package Inst2 is new Gen2(Inst1.A, Inst2.B, others => <>); ... package GP is ... The parameters which are not specified may be referenced by name as expanded names using the formal package as its prefix. For example, Inst2.FT3 and Inst2.FT4 may be used later in the formal generic part of GP or within the specification or body of GP. By contrast, the specified actuals may not be so named, to avoid confusion between the properties of the actual and those of the formal. Similarly, any implicit declarations associated with a given parameter of the formal package may be named using the formal package as a prefix only when the actual for the parameter is *not* specified. With this proposal, the notation "(<>)" for its actual part is essentially a short-hand for "(others => <>)." !wording Replace 12.7(3) with: formal_package_actual_part ::= (<>) | [generic_actual_part] | ([generic_association {, generic_association},] OTHERS => <>) Any positional generic_associations shall precede any named generic_associations. Replace 12.7(5) with the following: The actual shall be an instance of the template. If the formal_package_actual_part is (<>) or (OTHERS => <>), then the actual may be any instance of the template; otherwise, certain of the actual parameters of the actual instance shall match the corresponding actual parameter of the formal package, determined as follows: * If the formal_package_actual_part includes generic_associations as well as "OTHERS => <>", then only the actual parameters specified explicitly in these generic_associations are required to match; * Otherwise, all actual parameters shall match, whether the actual parameter is given explicitly or by default. The rules for matching of actual parameters between the actual instance and the formal package are as follows: Replace 12.7(10) with the following: The visible part of a formal package includes the first list of basic_declarative_items of the package_specification. In addition, for each actual parameter that is not required to match, a copy of the declaration of the corresponding formal parameter of the template is included in the visible part of the formal package. If the copied declaration is for a formal type, copies of the implicit declarations of the primitive subprograms of the formal type are also included in the visible part of the formal package. For the purposes of matching, if the actual instance is itself a formal package, then its actual parameters are those specified explicitly or implicitly in the formal_package_actual_part, plus, for those not specified, the copies of the formal parameters of the template included in the visible part of the actual instance. !discussion This is intended to be a natural generalization of the two capabilities currently provided for specifying actual parameters of a formal package. By providing this "mid-point" where some but not all of the parameters are specified, the formal package capability becomes significantly more useful, without measurably increasing the complexity of supporting the capability. There is an issue of which names are visible outside an instance: generic type T is new A; -- function F1 (X : T) return T; -- Implicit type U is new B; -- function F2 (X : U) return U; -- Implicit package GP is ... end GP; generic ... with package FP is new GP (T1, others => <>); -- Can use FP.U, cannot use FP.T. So FP.F2 is OK, and FP.F1 is illegal. Thus the 12.7(10) wording has been adjusted so as to include copies of primitive operations. This AI also answers a related question. If a generic formal package B whose actual part is (<>) is passed as an actual to another generic formal package A without (<>), then 12.7(5-8) requires the actuals of B to match the actuals of A. But what are the actuals of B? Clearly, they should be the entities denoted by names of the form B.x, where x is a generic formal parameter of B. 12.7(5-8) require the actual parameters of the actual package to match the actual parameters of the formal package. But if the actual package has (<>), then its actual parameters are denoted by the formal parameters. Consider the following illegal example: generic type T is private; package Template is X : T; end Template; with Template; generic type Ft1 is private; with package Formal_With_Actual is new Template( Ft1 ); package G1 is Y : Ft1 := Formal_With_Actual.X; end G1; with Template; generic type Ft2 is private; with package Formal_With_Box is new Template( <> ); package G2 is package I3 is new G1( Ft2, Formal_With_Box ); -- Illegal! end G2; The above is illegal, because the actual for Formal_With_Box is Formal_With_Box.T, and this does not statically match Ft2 (or anything else). Note that if the above were legal, the following would cause trouble: with Template, G2; package Instantiator is package I1 is new Template( Integer ); package I2 is new G2( Boolean, I1 ); end Instantiator; because I2 contains a variable (Y) of type Boolean, initialized to I1.X, which is of type Integer. Note that we cannot defer the check of I3 until the instantiation of G2, because I3 could be in the *body* of G2 (instead of in the specification, as shown above), and this would constitute a contract model violation. Now, consider the following legal example: generic type T1 is private; package G1 is ... end G1; generic type T2 is private; with package FP2 is new G1(T2); package G2 is ... end G2; generic with package FP3 is new G1(<>); package G3 is package I2 is new G2(T2 => FP3.T1, FP2 => FP3); -- OK. ... end G3; The instantiation I2 is legal because the actual for T2 is FP3.T1, which matches FP3.T1. !example Imagine a generic signature package with two formal parameters: generic type T is private; Obj : T package Sig is end; Now imagine there is a layered abstraction that wants two instances of this signature, and wants them to share the same type T, but not necessarily the same object "Obj". generic with package P1 is new Sig(<>); with package P2 is new Sig(P1.T, others => <>); package Layered_Abstraction is X : P1.T := P2.Obj; -- Both P1.T and P2.Obj are visible because -- they were not specified in the formal package. -- Note that P2.T is not visible since it -- is required to match P1.T ... end Layered_Abstraction; Note that this exact situation came up during the design of the physical units AI (AI-324). We wanted to pull out some of the nested generics from the large "System_Of_Units" generic. This would require the Unit_Signature generic signature package to have at least one additional parameter, the Names_Of_Dimensions: generic type Names_Of_Dimensions is (<>); Name : in String; Exponents : in Exponent_Array; Scale_Factor : in Scale_Type; type Value is digits <>; package Unit_Signature is end; But the use of these generics causes problems. If a "product" unit is constructed from two individual units: generic with package Unit_A is new Unit_Signature(<>); with package Unit_B is new Unit_Signature(Unit_A.Names_Of_Dimensions, others => <>); package Product_Unit is type Value is ... ... end Product_Unit; It is necessary that the Names_Of_Dimensions types are the same. With the Ada 95 rule, we'd have to pass in all of the other parameters separately to be able to force a match on just one of them: generic with package Unit_A is new Unit_Signature(<>); Unit_B_Name : in String; Unit_B_Exponents : in Exponent_Array; Unit_B_Scale_Factor : in Scale_Type; type Unit_B_Value is digits <>; with package Unit_B is new Unit_Signature(Unit_A.Names_Of_Dimensions, Unit_B_Name, Unit_B_Exponents, Unit_B_Scale_Factor, Unit_B_Value); package Product_Unit is type Value is ... ... end Product_Unit; This is clearly much less useful, and creates an asymmetric requirement when instantiating, where information about Unit_A can be passed in using a single signature instance, whereas Unit_B requires four additional formal parameters and then a largely redundant signature instance as well. !corrigendum 12.7(3) @drepl @xcode<@fa) | [generic_actual_part]>> @dby @xcode<@fa) | [generic_actual_part] | ([generic_association {, generic_association},] >@ft<@b>@fa< =@> <@>)>> Any positional @fas shall precede any named @fas. !corrigendum 12.7(5) @drepl The actual shall be an instance of the template. If the @fa is (<@>), then the actual may be any instance of the template; otherwise, each actual parameter of the actual instance shall match the corresponding actual parameter of the formal package (whether the actual parameter is given explicitly or by default), as follows: @dby The actual shall be an instance of the template. If the @fa is (<@>) or (@b =@> <@>), then the actual may be any instance of the template; otherwise, certain of the actual parameters of the actual instance shall match the corresponding actual parameter of the formal package, determined as follows: @xbullet includes @fas as well as "@b =@> <@>", then only the actual parameters specified explicitly in these @fa are required to match;> @xbullet The rules for matching of actual parameters between the actual instance and the formal package are as follows: !corrigendum 12.7(10) @drepl The visible part of a formal package includes the first list of @fa of the @fa. In addition, if the @fa is (<@>), it also includes the @fa of the template for the formal package. @dby The visible part of a formal package includes the first list of @fa of the @fa. In addition, for each actual parameter that is not required to match, a copy of the declaration of the corresponding formal parameter of the template is included in the visible part of the formal package. If the copied declaration is for a formal type, copies of the implicit declarations of the primitive subprograms of the formal type are also included in the visible part of the formal package. For the purposes of matching, if the actual instance is itself a formal package, then its actual parameters are those specified explicitly or implicitly in the @fa, plus, for those not specified, the copies of the formal parameters of the template included in the visible part of the actual instance. !ACATS test Create ACATS tests to check this feature. Also, create B and C tests out of the examples in the discussion. !appendix !section 12.7(0) !subject Generic Contract Model Violation ? !reference AARM95-12.7;6.0 !from Jesper Joergensen 95-08-16 !reference as: 95-5257.a Jesper Joergensen 95-8-16>> !discussion The use of a formal package as an actual to another formal package is a quite complex matter and as far as I can see we have a contract model violation with the present rules. Consider the example (I'm sorry, but I don't think this example can be shorter): -- first the "template" in the sense of [AARM 12.7(4)]: generic type T is private; package Template is X : T; end Template; -- then a formal package using the template: with Template; generic type Ft1 is private; with package Formal_With_Actual is new Template( Ft1 ); package G1 is Y : Ft1 := Formal_With_Actual.X; end G1; -- then another formal package using the template: with Template; generic type Ft2 is private; with package Formal_With_Box is new Template( <> ); package G2 is pragma Elaborate_Body; -- just to make a body for G2 legal end G2; -- then a unit instantiating G2: with Template, G2; package Instantiator is package I1 is new Template( Integer ); package I2 is new G2( Boolean, I1 ); end Instantiator; -- so far nothing is wrong (all legality rules are fulfilled), but if the -- body of G2 contains an instantiation of G1 using its own formal -- parameters as the actuals, we have a problem: with G1; package body G2 is package I3 is new G1( Ft2, Formal_With_Box ); end G2; This is a legal instantiation as far as I can see. The result of all this is that we have a package instance I2 with the following contents: package I2 is pragma Elaborate_Body; end I2; package body I2 is -- package I3 is new G1( Boolean, I1 ): package I3 is Y : Boolean := I1.X; end I3; end I2; And here we have a boolean variable initialized to that of an integer value! because we have associated the formal type T with both of these types. 1. Is the above analysis correct ? 2. If yes, don't we need a legality rule that forbids using a formal package with a box as an actual package for a formal package without box. As far as I can see this kind of instantiation is the only one requiring an extra check in an instance (for an enclosed instance) for the rules 12.7(6-8). In all other cases we only need to check for these rules at the place of the individual instantiations. In the context of the above example, we can't check the rules at the place of G2.I3 because we still don't know the actuals for Formal_With_Box. /Jesper, DDC-I **************************************************************** !section 12.7(00) !subject Generic Contract Model Violation ? !reference AARM95-12.7;6.0 !reference 95-5257.a Jesper Joergensen 95-08-16 !from Tucker Taft 95-08-16 !reference as: 95-5260.a Tucker Taft 95-8-17>> !discussion > The use of a formal package as an actual to another formal package is a quite > complex matter and as far as I can see we have a contract model violation with > the present rules. Consider the example (I'm sorry, but I don't think this > example can be shorter): > > > -- first the "template" in the sense of [AARM 12.7(4)]: > > generic > type T is private; > package Template is > X : T; > end Template; > > > -- then a formal package using the template: > > with Template; > generic > type Ft1 is private; > with package Formal_With_Actual is new Template( Ft1 ); > package G1 is > Y : Ft1 := Formal_With_Actual.X; > end G1; > > > -- then another formal package using the template: > > with Template; > generic > type Ft2 is private; > with package Formal_With_Box is new Template( <> ); > package G2 is > pragma Elaborate_Body; -- just to make a body for G2 legal > end G2; > > > -- then a unit instantiating G2: > > with Template, G2; > package Instantiator is > package I1 is new Template( Integer ); > package I2 is new G2( Boolean, I1 ); > end Instantiator; > > > -- so far nothing is wrong (all legality rules are fulfilled), but if the > -- body of G2 contains an instantiation of G1 using its own formal > -- parameters as the actuals, we have a problem: > > with G1; > package body G2 is > package I3 is new G1( Ft2, Formal_With_Box ); This violates 12.7(5), since the actual parameter of the "instance" Formal_With_Box is Formal_With_Box.T, and this does not statically match Ft2. > end G2; > > This is a legal instantiation as far as I can see. No, it violates 12.7(5). When inside a generic, a formal-package-with-box F looks like an instance whose actual parameters are F.formal1, F.formal2, etc. These "actual" parameters only match themselves for the purposes of 12.7(6..8), since nothing else is known about them. Perhaps an explicit clarification of this in the RM would be helpful. > ... > 1. Is the above analysis correct ? No. > ... > /Jesper, DDC-I -Tuck **************************************************************** !section 12.7(00) !subject Generic Contract Model Violation ? !reference AARM95-12.7;6.0 !reference 95-5257.a Jesper Joergensen 95-8-16 !from Jesper Joergensen 95-08-16 !reference as: 95-5261.a Pascal Leroy 95-8-17>> !discussion > -- first the "template" in the sense of [AARM 12.7(4)]: > > generic > type T is private; > package Template is > X : T; > end Template; > > -- then a formal package using the template: > > with Template; > generic > type Ft1 is private; > with package Formal_With_Actual is new Template( Ft1 ); > package G1 is > Y : Ft1 := Formal_With_Actual.X; > end G1; > > -- then another formal package using the template: > > with Template; > generic > type Ft2 is private; > with package Formal_With_Box is new Template( <> ); > package G2 is > pragma Elaborate_Body; -- just to make a body for G2 legal > end G2; > > -- so far nothing is wrong (all legality rules are fulfilled), but if the > -- body of G2 contains an instantiation of G1 using its own formal > -- parameters as the actuals, we have a problem: > > with G1; > package body G2 is > package I3 is new G1( Ft2, Formal_With_Box ); > end G2; > > This is a legal instantiation as far as I can see. The result of all this is > that we have a package instance I2 with the following contents: I may have an overly optimistic reading of the RM, but this instantiation seems illegal to me. RM95 12.7(5) states that "each actual parameter of the actual instance shall match the corresponding actual parameter of the formal package". In addition, RM95 12.3(3-4) indicates that actual parameters are provided by a generic_actual_part. Now the syntax in RM95 12.7(3) clearly says that "(<>)" is _not_ a generic_actual_part. >From these rules I draw the conclusion that your Formal_With_Box has no actual parameters, and therefore that the instantiation I3 is illegal, because the actual parameters don't match the formal parameters. Note that following this reasoning, I3 would be legal if Template had an empty generic_formal_part: Formal_With_Actual would have an empty generic_actual_part, and in this case the actual parameters of Formal_With_Box would match those of Formal_With_Actual. But I don't see that you could come up with a contract model violation with empty formal parts... > 1. Is the above analysis correct ? > 2. If yes, don't we need a legality rule that forbids using a formal package > with a box as an actual package for a formal package without box. As far as > I can see this kind of instantiation is the only one requiring an extra > check in an instance (for an enclosed instance) for the rules 12.7(6-8). > In all other cases we only need to check for these rules at the place of > the individual instantiations. In the context of the above example, we > can't check the rules at the place of G2.I3 because we still don't know > the actuals for Formal_With_Box. Even if your analysis was correct (which I doubt), it would not be a good idea to do the check in the instance. If we want to avoid all sorts of nasty dependences on the contents of the generic bodies, the check must be done at the place of G2.I3, "assuming the worst" (as is already the case for other rules). Pascal. _____________________________________________________________________ Pascal Leroy +33.1.30.12.09.68 pleroy@rational.com +33.1.30.12.09.66 FAX **************************************************************** From the editor, July 7, 2000 At the Potsdam ARG meeting (the 11th ARG meeting), it was decided that AI-86 should not appear in the Records of Response, as it no one was able to provide a explanation as to how the the conclusion follows from the existing text of the RM. Moreover, we didn't feel capable to write that text at this time. AI-86 was be changed back to a work item, in order to either find an appropriate explanation, or to decide on wording to implement the recommendation (that is, a change in status from !confirmation to !binding interpretation). [It was later folded into AI-317.] **************************************************************** From: Tucker Taft Semt: Sunday, September 28, 2003 3:41 PM Here is an update to AI-317. Not much change. I was supposed to add something to 12.7(10) to fix a problem relating to "formal.formal.xxx" but I can't remember the details. Does anyone have a simple example to illustrate the problem? I think Erhard brought it up a few times, but the ARG minutes don't elaborate, as far as I can see. [Editor's note: This is version /03 of the AI.] **************************************************************** From: Mario Amado Alves Semt: Tuesday, September 30, 2003 1:04 PM In Ada 95 the formal_package_actual_part is either the box or it must list *all* the type parameters (Note 1). But sometimes a partial list would be useful: generic type Formal_1 is private; type Formal_2 is private; ... package Template is ... end; type Special_Actual is ...; generic with package Special_Template is new Template (Formal_1 => Special_Actual); -- PARTIAL LIST HERE (NOTE 2) ... package Generic_Special_Unit is ... end; package Special_Template is new Template (Formal_1 => Special_Actual, Formal_2 => ..., ...); package Special_Unit is new Generic_Special_Unit (Special_Template, ...); This only requires modification to 12.7. If there is interest I'll try to formalize an AI. Thanks. NOTES 1. See RM 12.7 (3). I don't find this required completness a clear ramification, but that is another story. 2. Not Ada 95. Alternate syntaxes (also not Ada 95): (Formal_1 => Special_Actual, <>); (Formal_1 => Special_Actual, others => <>); **************************************************************** From: Randy Brukardt Semt: Tuesday, September 30, 2003 5:53 PM This is AI-317. Please check for existing AIs before starting new discussions; it just makes more work for me. (Of course, comments on existing AIs are fine.) **************************************************************** From: Mario Amado Alves Semt: Tuesday, September 30, 2003 6:27 PM Indeed it is! Thanks. I do search the AIs before posting, but on this case it seems I missed it for some reason. Sorry. **************************************************************** From: Tucker Taft Semt: Monday, June 7, 2004 11:07 PM Here is an update to AI 317 [This is version /06 of the AI - ED] that includes the confirmation provided by AI-86 for the case when the actual instance is itself a formal package. The only change was to add the following paragraph at the end of 12.7: For the purposes of matching, if the actual instance is itself a formal package, then its actual parameters are those specified explicitly or implicitly in the formal package actual part, plus, for those not specified, the copies of the formal parameters of the template included in the visible part of the actual instance. That is admittedly quite a sentence. ;-) **************************************************************** From: Randy Brukardt Semt: Wednesday, June 9, 2004 10:42 PM > Here is an update to AI 317 that includes the confirmation > provided by AI-86 for the case when the actual instance is > itself a formal package. The only change was to add > the following paragraph at the end of 12.7: I think it would be unfortunate to lose the examples and discussion from AI-86 (which would happen as the AI would be deleted since it was folded into AI-317). They would make good ACATS tests, if nothing else. But since the problem is real and requires wording to fix, it would be useful to explain the problem and the fix. > For the purposes of matching, if the actual instance is itself a > formal package, then its actual parameters are those specified > explicitly or implicitly in the formal package actual part, plus, for > those not specified, the copies of the formal parameters of the > template included in the visible part of the actual instance. > > That is admittedly quite a sentence. ;-) Sure is. I wonder what it means? :-) In particular, what's an "actual part"? There's no such term in the Standard's index. Do you mean "actual parameter list"? Or maybe you meant "formal_package_actual_part" (the syntactic entity). **************************************************************** From: Tucker Taft Semt: Thursday, June 10, 2004 12:06 AM > I think it would be unfortunate to lose the examples and > discussion from AI-86 (which would happen as the AI would be > deleted since it was folded into AI-317). They would make good > ACATS tests, if nothing else. But since the problem is real and requires > wording to fix, it would be useful to explain the problem and the fix. Can we just concatenate the AI-86 discussion and examples to that of AI-317? I would think that would work with just a bit of smoothing. >> For the purposes of matching, if the actual instance is itself a >> formal package, then its actual parameters are those specified >> explicitly or implicitly in the formal package actual part, plus, for >> those not specified, the copies of the formal parameters of the >> template included in the visible part of the actual instance. >> >>That is admittedly quite a sentence. ;-) > > > Sure is. I wonder what it means? :-) In particular, what's an > "actual part"? There's no such term in the Standard's index. Do you mean > "actual parameter list"? Or maybe you meant "formal_package_actual_part" > (the syntactic entity). The phrase "formal package actual part" should have been the syntactic entity "formal_package_actual_part." ****************************************************************