!standard 13.1.1(4/5) 20-04-26 AI12-0355-1/02 !standard 13.1.1(12/5) !standard 13.1.1(18.7/5) !standard 13.1.1(36/3) !class Amendment 20-01-12 !status work item 20-01-12 !status received 19-12-18 !priority Medium !difficulty Medium !subject Generalized aspect specifications !summary Define a syntax for specifying aspects based on a user-defined type, so implementations can support a more easily parameterized "plug-in" architecture for features such as light-weight parallelism schedulers, analogous to the existing plug-in architecture that exists for Storage_Pools and Subpools. All constructs that include the word "parallel" now permit an aspect_specification as part of their syntax. !problem We need a mechanism to pass information through an implementation-supported API to an underlying user-provided library, similar to the way that Storage_Pools are supported today, to give users more flexibility in supporting advanced features like schedulers for light-weight parallelism. We imagine that third-party libraries like OpenMP might be used, and these libraries often have many tuning options. Something like an aspect specification might be a good way to specify such options, but it seems important that the Ada compiler need not be updated every time the underlying library provides another tuning option. Having a forest of implementation-defined pragmas and aspects for this purpose seems like overkill, and would require the compiler to track the changing needs of all these libraries. It seems that an extension of the aspect_specification notation could provide this mechanism without requiring implementation changes for each possible architecture. !proposal Add generalized aspect specifications: aspect_specification_element ::= aspect_association | generalized_aspect_specification aspect_association ::= aspect_mark [=> aspect_definition] generalized_aspect_specification ::= subtype_mark ( /component_/selector_name [=> expression] {, /component_/selector_name [=> expression]} ) aspect_specification ::= WITH aspect_specification_element{, aspect_specification_element} As part of this AI, we also propose to add an aspect_specification to every place the PARALLEL keyword is envisioned currently PARALLEL [(chunk_specification)] [aspect_specification] FOR ... This allows specifying language-defined aspects, as well as generalized aspects, in the same context. The semantics of the generalized_aspect_specification is that the user identifies with the subtype_mark a type that is a descendant of the type Ada.Aspects.Root_Aspect. The /component_/selector_name specify (visible) components of this descendant, with the corresponding expression being a value of the type of the component. As usual, if the component is of a boolean type, the aspect_definition defaults to "True". If the component's declaration has a default expression, then it need not be mentioned in the generalized_aspect_specification. !wording Replace 4.5.10 (3/5) with: value_sequence ::= '[' [parallel[(chunk_specification)] [aspect_specification]] iterated_element_association ']' Modify 4.5.10 (21/5): For the evaluation of a value_sequence, the iterated_element_association{, the chunk_specification, and the aspect_specification, if any, are elaborated in an arbitrary order} [is elaborated], then an iteration is performed, and for each value conditionally produced by the iteration (see 5.5 and 5.5.2), the associated expression is evaluated with the loop parameter having this value, to produce a result that is converted to Value_Type, and used to define the next value in the sequence. Replace 5.5 (3/5) with: iteration_scheme ::= while condition | for loop_parameter_specification | for iterator_specification | [parallel [aspect_specification]] for procedural_iterator | parallel [(chunk_specification)] [aspect_specification] for loop_parameter_specification | parallel [(chunk_specification)] [aspect_specification] for iterator_specification Modify 5.5 (9/5): For the execution of a loop_statement that has an iteration_scheme including a loop_parameter_specification, after elaborating the chunk_specification {and aspect_specification}, if any, the loop_parameter_specification is elaborated. ... Add to the end of 5.5.3 (25/5): ... The aspect_specification, if any, is elaborated prior to the invocation of the iterating procedure. Add to the end of 13.1.1 (1/3): ... {In this subclause we give the rules relating to an aspect_association appearing within an aspect_specification; see 13.2.2 for rules relating to a generalized_aspect_specification.} Replace 13.1.1 (2/3) with: aspect_specification ::= WITH aspect_specification_element{, aspect_specification_element} aspect_specification_element ::= aspect_association | generalized_aspect_specification aspect_association ::= aspect_mark [=> aspect_definition] There shall be at most one generalized_aspect_specification (see 13.1.2) in an aspect_specification. Modify 13.1.1 (37/3): At the freezing point of the associated entity, the aspect_specification is elaborated. {When appearing in a construct other than a declaration, an aspect_specification is elaborated as part of the execution of the construct.} The elaboration of the aspect_specification {consists of the elaboration of each aspect_specification_element in an arbitrary order. The elaboration of an aspect_specification_element that is an aspect_association consists of the elaboration of the aspect_definition, which} includes the evaluation of the name or expression, if any, unless the aspect itself is an expression. If the corresponding aspect represents an expression (as in a precondition), the elaboration has no effect; the expression is evaluated later at points within the execution as specified elsewhere in this International Standard for the particular aspect. {[Redundant: The elaboration of an aspect_specification_element that is a generalized_aspect_specification is described in 13.1.2.]} Add a new subclause 13.1.2: 13.1.2 Generalized Aspect Specifications A generalized_aspect_specification allows for associating with an entity or construct a value of a tagged type representing one or more user-defined aspects. Syntax generalized_aspect_specification ::= subtype_mark ( generalized_aspect_component {, generalized_aspect_component} ) generalized_aspect_component ::= /component_/selector_name [=> expression] Static Semantics The following language-defined package exists: package Ada.Aspects is type Root_Aspect is tagged null record; Null_Aspect : constant Root_Aspect := (null record); end Ada.Aspects; Name Resolution The subtype_mark of a generalized_aspect_specification shall resolve to denote a tagged type D that is a descendant of Ada.Aspects.Root_Aspect through one or more record extensions and no private extensions. The /component_/selector_name of a generalized_aspect_component shall resolve to denote a component C of D. If the component C is of a boolean type, an expression is optional. If an expression is given, its expected type is that of the component C. Legality Rules The type D shall not have a variant_part in the declaration of any of its ancestor record_extensions (including D itself). Each component of D shall be named at most once by a /component_/selector_name within a given generalized_aspect_specification. A component that is not named shall have a default expression in its declaration. It is implementation defined in what constructs it is legal for an an aspect_specification to include a generalized_aspect_specification, and whether there are any limitations on what descendants of Root_Aspect may be used. Static Semantics A generalized_aspect_specification defines a set of user-defined aspects, one for each generalized_aspect_component. This set of aspects is represented by a value of the tagged type D. If an expression is omitted from a generalized_aspect_component, it is equivalent to the expression being specified as True. Dynamic Semantics For the elaboration of a generalized_aspect_specification, a value of type D is created as though it were a record_aggregate (see 4.3.1), with one record_component_association for each generalized_aspect_component of the generalized_aspect_specification and one record_component_association for any component not named in the generalized_aspect_specification, associated with its default expression. The effect of specifying a generalized_aspect_specification is implementation defined. !examples Presuming that the following type is declared in a package Interfaces.OpenMP: type OMP_taskloop is new Ada.Aspects.Root_Aspect with record if_taskloop : Boolean := True; -- False means no parallelism grainsize : Natural := 0; -- 0 implies impl-defined default collapse : Positive := 1; -- greater than 1 means nested loops -- should be combined in work sharing end record; the implementation could allow a generalized aspect specification to occur in an aspect specification associated with a parallel loop such as: parallel with OpenMP.OMP_taskloop (collapse => 2, grainsize => 100_000) for I in 1 .. 10_000_000 loop ... end loop; The value of OMP_Taskloop created as a result of elaborating the generalized_aspect_specification would be passed through to the OpenMP lightweight thread scheduler as a value of type Ada.Aspects.Root_Aspect'Class. !discussion To allow passing tuning parameters through to user-provided libraries that are invoked implicitly as a result of certain language constructs, it is useful to generalize the notion of "aspect" to something whose structure and type can be defined by the underlying library, without the Ada compiler having built-in knowledge of the kind of tuning parameter that might be appropriate. The API for plugging in such a user-provided library need only include a parameter of type Root_Aspect'Class, defaulted to Null_Aspect, and the information in a generalized_aspect_specification can be passed through. For example, a hypothetical API to plug in a user-defined lightweight thread scheduler might contain the following: procedure LWT_Range_Loop (Data : Range_Loop.Range_Loop_Data'Class; Aspects : Ada.Aspects.Root_Aspect'Class := Ada.Aspects.Null_Aspect); -- Execute a light-weight-threading-based "range" loop, -- given optional aspect specification. When generating a call on such an API, the compiler will pass as the Aspects parameter the value of the type identified in the generalized_aspect_specification if present. If no such generalized_aspect_specification is present, the compiler would pass the default Null_Aspect value. In some cases, it might be more convenient to have an access parameter such as: ... Aspects: access constant Ada.Aspects.Root_Aspect'Class := null); Either can accomplish the goal of passing information through to the underlying library implementing the API, without the compiler needing any special knowledge of the kinds of information being passed through the Aspects parameter. !ASIS [Not sure. It seems like some new capabilities might be needed, but I didn't check - Editor.] !ACATS test ACATS B- and C-Tests are needed to check that the new capabilities are supported. !appendix From: Tucker Taft Sent: Wednesday, December 18, 2019 8:17 AM In our discussions of the parallel features of Ada 202X, we have talked about allowing more aspects to control or tune the underlying light-weight-threading implementation of, say, a given parallel loop. Here is one possible syntax: generalized_aspect_specification ::= WITH subtype_mark, aspect_mark [=> aspect_definition] {, aspect_mark [=> aspect_definition] } parallelism_control_specification ::= chunk_specification [generalized_aspect_specification] | generalized_aspect_specification iteration_scheme := ... PARALLEL [(parallelism_control_specification)] FOR loop_parameter_specification ... --- Here is an example: parallel (with OpenMP.OMP_taskloop, collapse => 2, grainsize => 100_000) for I in 1 .. 10_000_000 loop ... end loop; This usage indicates that a generalized aspect object of type OpenMP.OMP_taskloop should be created and passed along with the usual parameters to the interface used for invoking a parallel "range" loop. The expectation is that such interfaces, e.g. defined in the "Ada.Parallelism" package (or "System.Parallelism" to reflect implementation dependence) mentioned in presentation in the ARG meeting on mapping to OpenMP (see extract below), and called from code generated by the compiler, would have an Aspects parameter as illustrated below: procedure Par_Range_Loop (Low, High : Longest_Integer; Num_Chunks : Natural := 0; -- 0 means no chunk specification present Aspects : access Ada.Aspects.Root_Aspect'Class := null; -- null means no aspects specified Loop_Body : access procedure (Low, High : Longest_Integer; Chunk_Index : Positive)); The semantics of the generalized_aspect_specification would be that the user identifies with the subtype_mark a type that is a record extension of (say) Ada.Aspects.Root_Aspect (OpenMP.OMP_taskloop in the above example), and then uses the (visible) components of this record extension as possible names that can be used as an aspect_mark, with the corresponding aspect_definition being a value of the type of the component. As usual, if the component is of a boolean type, the aspect_definition defaults to "True." If the component's declaration has a default expression, then it need not be mentioned in the generalized_aspect_specification. The declaration for OpenMP.OMP_taskloop (based on "taskloop" defined in https://www.openmp.org/wp-content/uploads/OpenMP-API-Specification-5.0.pdf) might be: type OMP_taskloop is new Ada.Aspects.Root_Aspect with record if_taskloop : Boolean := True; -- False means no parallelism grainsize : Natural := 0; -- 0 implies impl-defined default collapse : Positive := 1; -- greater than 1 means nested loops -- should be combined in work sharing end record; This provides a way for additional control to be passed along to an underlying implementation, such as OpenMP in this case, without resorting to ad-hoc compiler-provided special pragmas or aspects. Every compiler would support such an aspect, despite it being something that is part of a particular light-weight-threading scheduler like OpenMP. Comments welcome! -------- Extract from presentation on mapping Ada 202X to OpenMP from October ARG meeting -------- [NOTE: Have since had recommendations that this become "System.Parallelism" to reflect that Ada 202X implementations might define their own interfaces, perhaps using this proposal as a model.] Expansion proposal: Expansions for Ada 202X parallel loop: ... parallel (Num_Chunks) for I in A .. B loop end loop; ... expands into: declare procedure I__Loop_Body (I__Low, I__High : Longest_Integer; I__Chunk_Index : Positive) is begin for I in S'Val (I__Low) .. S'Val (I__High) loop end loop; end I__Loop_Body; begin Ada.Parallelism.Par_Range_Loop (S'Pos(A), S'Pos(B), Num_Chunks, I__Loop_Body'Access); end; ... Ada.Parallelism package The Ada.Parallelism package spec would contain (at least) the following: package Ada.Parallelism is type Longest_Integer is range System.Min_Int .. System.Max_Int; -- Not worrying about unsigned ranges with upper bound > System.Max_Int for now. -- Could be handled by having a version of Par_Range_Loop that operates on -- unsigned integers. procedure Par_Range_Loop (Low, High : Longest_Integer; Num_Chunks : Positive; Loop_Body : access procedure (Low, High : Longest_Integer; Chunk_Index : Positive)); ... end Ada.Parallelism; **************************************************************** From: Richard Wai Sent: Wednesday, December 18, 2019 8:57 AM > ... Here is one possible syntax: > > generalized_aspect_specification ::= > WITH subtype_mark, > aspect_mark [=> aspect_definition] {, > aspect_mark [=> aspect_definition] } I'm a little bit incredulous about the comma separating the subtype_mark from a list of aspect_marks. This seems a bit unclear to read, since it appears as a list, which are usually homogenous. I wonder if this makes more sense: generalized_aspect_specification ::= WITH subtype_mark USE aspect_mark [=> aspect_definition] {, aspect_mark [=> aspect_definition] } > Here is an example: > > parallel (with OpenMP.OMP_taskloop, collapse => 2, grainsize => 100_000) > for I in 1 .. 10_000_000 loop > ... > end loop; > Would become: parallel (with OpenMP.OMP_taskloop use collapse => 2, grainsize => 100_000) for I in 1 .. 10_000_000 loop ... end loop; Otherwise, the concept of generalized aspects seems like an interesting idea! **************************************************************** From: Tucker Taft Sent: Wednesday, December 18, 2019 9:22 AM >I wonder if this makes more sense: > >generalized_aspect_specification ::= > WITH subtype_mark > USE aspect_mark [=> aspect_definition] {, > aspect_mark [=> aspect_definition] } Not thrilled with "use" here! Perhaps just use a colon, then the syntax fits nicely within an overall aspect specification syntax: aspect_specification ::= WITH [subtype_mark : ] aspect_mark ... ... >Would become: > > parallel (with OpenMP.OMP_taskloop use collapse => 2, grainsize => 100_000) > for I in 1 .. 10_000_000 loop > ... > end loop; parallel (with OpenMP.OMP_taskloop : collapse => 2, grainsize => 100_000) for I in 1 .. 10_000_000 loop ... end loop; >Otherwise, the concept of generalized aspects seems like an interesting idea! Glad to hear it. **************************************************************** From: Randy Brukardt Sent: Wednesday, December 18, 2019 5:42 PM > In our discussions of the parallel features of Ada 202X, we have > talked about allowing more aspects to control or tune the underlying > light-weight-threading implementation of, say, a given parallel loop. > Here is one possible syntax: > > generalized_aspect_specification ::= > WITH subtype_mark, > aspect_mark [=> aspect_definition] {, > aspect_mark [=> aspect_definition] } The basic idea seems sound. I wonder if "generalized" aspect specification is really the right name, given that it only seems to be used in one context. It's more like a "parallelism_aspect_specification". Of course, if we find additional contexts in the future, the more general name makes sense. >I'm a little bit incredulous about the comma separating the >subtype_mark from a list of aspect_marks. This seems a bit unclear to >read, since it appears as a list, which are usually homogenous. Agreed. >Not thrilled with "use" here! Perhaps just use a colon, then the >syntax fits nicely within an overall aspect specification syntax: I prefer "use" to ":", because this use of colon is backwards the usual use (the subtype is on the right of a colon in declarations). That seems like a point of confusion. It's clearer with the keyword that this is a special construct. Back to Tucker's original message: ... > The expectation is that such > interfaces, e.g. defined in the "Ada.Parallelism" package (or > "System.Parallelism" to reflect implementation dependence) mentioned > in presentation in the ARG meeting on mapping to OpenMP (see extract > below), and called from code generated by the compiler, would have an > Aspects parameter as illustrated below: > > procedure Par_Range_Loop > (Low, High : Longest_Integer; > Num_Chunks : Natural := 0; -- 0 means no chunk specification present > Aspects : access Ada.Aspects.Root_Aspect'Class := null; > -- null means no aspects specified > Loop_Body : access procedure > (Low, High : Longest_Integer; Chunk_Index : Positive)); The aspects interface is rather similar to the one I used in Janus/Ada to represent aspect_specification. This is, it is a list of aspect name/aspect value pairs. (The compiler doesn't need an extension as it is using unevaluated expression trees as the value -- that wouldn't work at compile time.) > The semantics of the generalized_aspect_specification would be that > the user identifies with the subtype_mark a type that is a record > extension of (say) Ada.Aspects.Root_Aspect (OpenMP.OMP_taskloop in the > above example), and then uses the > (visible) components of this record extension as possible names that > can be used as an aspect_mark, with the corresponding > aspect_definition being a value of the type of the component. As > usual, if the component is of a boolean type, the aspect_definition > defaults to "True." If the component's declaration has a default > expression, then it need not be mentioned in the > generalized_aspect_specification. This seems a bit too magic for my taste. It's pretty much a reflection mechanism for this one case. Moreover, it doesn't seem to work well for things that can't be components (in particular, unconstrained strings, typically used for user-defined names, debugging messages, and the like). I'd hate to have to use fixed length debugging strings. Here I admit that I don't have an obviously better idea. I'd probably simply implement the thing Janus/Ada does, a list of name/value pairs and let the user-defined routine sort them out. That does have the problem of not defining the resolution of the values very well. If we were going to follow this idea, it would be valuable to make it more generally available across the entire language -- although it's not completely clear how that would work. Perhaps a mechanism like this would be a better way to deal with aspects that involve a set of parameters (such as the user-defined aggregate thing). That would suggest that one could have a list of these things, where each one is an aspect specification of it's own. For instance, the Vector definition would then look something like: type Vector is tagged private with Constant_Indexing => Constant_Reference, Variable_Indexing => Reference, Default_Iterator => Iterate, Iterator_Element => Element_Type, Iterator_View => Stable.Vector, Aggregate => Ada.Aggregates.Aggregate_Definition use (Empty => Empty'access, Add_Unnamed => Append_One'access, New_Indexed => New_Vector'access, Assign_Indexed => Replace_Element'access), Stable_Properties => Ada.Contracts.Stable_Properties use (F1 => Length'access, F2 => Capacity'access, F3 => Tampering_With_Cursors_Prohibited'access, F4 => Tampering_With_Elements_Prohibited'access), Default_Initial_Condition => Length (Vector) = 0 and then (not Tampering_With_Cursors_Prohibited (Vector)) and then (not Tampering_With_Elements_Prohibited (Vector)); Brainstorming here, not sure this makes sense. (Or clarifies anything.) **************************************************************** From: Tucker Taft Sent: Saturday, December 21, 2019 2:35 PM > Some random thoughts on this proposal: > >> In our discussions of the parallel features of Ada 202X, we have >> talked about allowing more aspects to control or tune the underlying >> light-weight-threading implementation of, say, a given parallel loop. >> Here is one possible syntax: >> >> generalized_aspect_specification ::= >> WITH subtype_mark, >> aspect_mark [=> aspect_definition] {, >> aspect_mark [=> aspect_definition] } > > The basic idea seems sound. I wonder if "generalized" aspect > specification is really the right name, given that it only seems to be > used in one context. It's more like a "parallelism_aspect_specification". I could see it used in other cases where there are places that a user can provide an implementation of an underlying capability. The Storage_Pool comes to mind. Some future ownership-based automatic storage management might be another. ... >> Not thrilled with "use" here! Perhaps just use a colon, then the >> syntax fits nicely within an overall aspect specification syntax: > > I prefer "use" to ":", because this use of colon is backwards the > usual use (the subtype is on the right of a colon in declarations). > That seems like a point of confusion. It's clearer with the keyword > that this is a special construct. Yes, I realized that the use of ":" was somewhat backwards, but it didn't bother me too much as it is a pretty different context. On the other hand, it feels odd to insert "use" here, when we have become accustomed to "with" introducing the specification of aspects. So on further thought, it seems like we might want to integrate this generalize aspect specification as part of a "normal" aspect specification, so one would want a way to know where the generalize aspects end. Hence, I thought that perhaps a notation somewhat like a discriminant constraint might work. So if we introduce an aspect_association syntactic construct, then we could define a simple_aspect_association and a generalized_aspect_association, and allow a sequence of them in an aspect_specification: aspect_association ::= simple_aspect_association | generalized_aspect_association simple_aspect_association ::= aspect_mark [=> aspect_definition] generalized_aspect_association ::= subtype_mark ( /component_/selector_name [=> expression] {, /component_/selector_name [=> expression]} ) aspect_specification ::= WITH aspect_association{, aspect_association} Then this could be used in a parallel construct as: PARALLEL [(chunk_specification)] [aspect_specification] FOR ... so we could specify language-defined aspects, as well as generalized aspects, in the same context. > ... > This seems a bit too magic for my taste. It's pretty much a reflection > mechanism for this one case. I'm not sure I understand why this is specific to this one case. It seems pretty general. > Moreover, it doesn't seem to work well for things that can't be > components (in particular, unconstrained strings, typically used for > user-defined names, debugging messages, and the like). > I'd hate to have to use fixed length debugging strings. It seems like we could use components of an anonymous access type to allow indefinite types, and then allow the value to be specified without the enclosing "new D'( ... )" since in this case that is pretty much just "noise." > Here I admit that I don't have an obviously better idea. I'd probably > simply implement the thing Janus/Ada does, a list of name/value pairs > and let the user-defined routine sort them out. That does have the > problem of not defining the resolution of the values very well. Yes, I thought about that approach, but it provides no compile-time checking whatsoever, and forces run-time parsing of the expressions, which seems much less friendly. > If we were going to follow this idea, it would be valuable to make it > more generally available across the entire language -- although it's > not completely clear how that would work. Perhaps a mechanism like > this would be a better way to deal with aspects that involve a set of > parameters (such as the user-defined aggregate thing). I have suggested a more general approach above, which seems like it is going in somewhat the same direction. **************************************************************** From: Randy Brukardt Sent: Sunday, December 22, 2019 9:00 PM ... >> The basic idea seems sound. I wonder if "generalized" aspect >> specification is really the right name, given that it only seems to >> be used in one context. It's more like a "parallelism_aspect_specification". > >I could see it used in other cases where there are places that a user >can provide an implementation of an underlying capability. The >Storage_Pool comes to mind. Some future ownership-based automatic >storage management might be another. A storage pool object can have discriminants already, so having another way to do essentially the same thing doesn't seem to buy much. Ownership-based storage management does seem to be another place where this could be useful. (I already noted the possibility of describing the "Aggregate" semantics using this construct -- it gets a bit clunky to describe the element type but the rest models fairly well.) ... > So on further thought, it seems like we might want to integrate this > generalize aspect specification as part of a "normal" aspect > specification, so one would want a way to know where the generalize > aspects end. Hence, I thought that perhaps a notation somewhat like a > discriminant constraint might work. So if we introduce an > aspect_association syntactic construct, then we could define a > simple_aspect_association and a generalized_aspect_association, and > allow a sequence of them in an aspect_specification: > > aspect_association ::= > simple_aspect_association | generalized_aspect_association > > simple_aspect_association ::= > aspect_mark [=> aspect_definition] > > generalized_aspect_association ::= > subtype_mark ( /component_/selector_name [=> expression] > {, /component_/selector_name [=> expression]} ) > > aspect_specification ::= WITH aspect_association{, aspect_association} > > Then this could be used in a parallel construct as: > > PARALLEL [(chunk_specification)] [aspect_specification] FOR ... > > so we could specify language-defined aspects, as well as generalized > aspects, in the same context. This seems more "generalized", and probably is a better idea than your original idea. One quibble, though: a paren is a bit subtle of a distinction between an aspect_mark standing alone (like "Pack") and a subtype_mark, and they obviously resolve very differently. Again, I don't off-hand have a better idea, so perhaps I ought to shut up. ;-) > > Back to Tucker's original message: > > ... > > This seems a bit too magic for my taste. It's pretty much a > > reflection mechanism for this one case. > > I'm not sure I understand why this is specific to this one case. It > seems pretty general. "This one case" means "generalized aspect specifications". It *does* seem pretty general, which is the concern in my mind -- we don't have any sort of reflection in any other context. Of course, your new syntax proposal makes it more like an aggregate, which of course is not a new idea. So perhaps changing the syntax makes this concern OBE. > > Moreover, it doesn't seem to work well for things that can't be > > components (in particular, unconstrained strings, typically used for > > user-defined names, debugging messages, and the like). > > I'd hate to have to use fixed length debugging strings. > > It seems like we could use components of an anonymous access type to > allow indefinite types, and then allow the value to be specified > without the enclosing "new D'( ... )" since in this case that is > pretty much just "noise." NOOOOOOOO!!!!!! Let's not expand the mistake of anonymous access types. Even an iota. :-) ... > > If we were going to follow this idea, it would be valuable to make > > it more generally available across the entire language -- although > > it's not completely clear how that would work. Perhaps a mechanism > > like this would be a better way to deal with aspects that involve a > > set of parameters (such as the user-defined aggregate thing). > > I have suggested a more general approach above, which seems like it is > going in somewhat the same direction. Yup, that's what I meant. You've already addressed it. **************************************************************** From: Randy Brukardt Sent: Sunday, January 12, 2020 4:13 PM ... > One quibble, though: a paren is a bit subtle of a distinction between > an aspect_mark standing alone (like "Pack") and a subtype_mark, and > they obviously resolve very differently. To clarify what I was talking about here, aspect_marks aren't reserved in any way. So one can declare objects and subtypes and the like with the same name. So there is a possibility of confusion if someone uses an aspect_mark as the name of a subtype. For instance: type Atomic is new OpenMP.OpenMP_object with record Copy : Boolean := False; end record; Then we could have: Data : Data_Type with Atomic; vs. Data : Data_Type with Atomic(Copy => True); which obviously would be confusing. And error handling could get messy if someone wrote something like: Data : Data_Type with Size(1); since the error message would be something like "no type Size" rather than incorrect syntax. Not a big deal, since it is mostly avoidable, and error handling only becomes an issue for large syntax mistakes (which are less likely than leaving out a comma). ****************************************************************