Version 1.7 of ais/ai-00317.txt
!standard 12.07 (03) 03-12-03 AI95-00317/05
!standard 12.07 (05)
!standard 12.07 (10)
!class amendment
!status Amendment 200Y 03-10-23
!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.
!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;
--
type U is new B;
--
package GP is ... end GP;
generic
...
with package FP is new GP (T1, others => <>);
--
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.
!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; --
--
--
--
...
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)
Replace the paragraph:
formal_package_actual_part ::=
(<>) | [generic_actual_part]
by:
formal_package_actual_part ::=
(<>)
| [generic_actual_part]
| ([generic_association {, generic_association},] others => <>)
Any positional generic_associations shall precede any named
generic_associations.
!corrigendum 12.7(5)
Replace the paragraph:
The actual shall be an instance of the template. If the
formal_package_actual_part 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:
by:
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:
!corrigendum 12.7(10)
Replace the paragraph:
The visible part of a formal package includes the first list of
basic_declarative_items of the package_specification. In addition,
if the formal_package_actual_part is (<>), it also includes the
generic_formal_part of the template for the formal package.
by:
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.
!ACATS test
Create an ACATS test to check this feature.
!appendix
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.
****************************************************************
Questions? Ask the ACAA Technical Agent