!standard 4.9(6) 18-01-05 AI12-0075-1/05 !standard 4.9(18) !class Amendment 13-06-09 !status work item 13-06-09 !status received 13-05-07 !priority Medium !difficulty Medium !subject Static expression functions !summary An expression function can be static in appropriate circumstances. !problem It should be possible to use an expression function in a static expression. This would allow greater abstraction for static expressions, which sometimes can get quite large. !proposal (See summary.) !wording Add to the definition of static function (i.e. insert as the penultimate item of the 4.9 (19-22) list): - a static expression function (see 6.8) Add at the and of the 4.9 "Legality Rules" section: AARM Discussion: The preceding "statically unevaluated" rule allows X : constant := (if True then 37 else (1 / 0)) but does not allow function If_Then_Else (Flag : Boolean; X, Y : Integer) is (if Flag then X else Y) with Static; -- see 6.8 X : constant := If_Then_Else (True, 37, 1 / 0); because evaluation of a function call includes evaluation of all of its actual parameters. Introduce a "Static Semantics" section for 6.8 immediately before the "Legality Rules" section, containing: A "potentially static expression" is defined in the same way as a static expression except that - a name denoting a formal parameter of an expression function is a potentially static expression; and - each use of "static expression" in the definition of "static expression" is replaced with a corresponding use of "potentially static expression" in the definition of "potentially static expression". AARM Discussion: These uses occur in the definition of "static expression" in the cases of function calls, type conversions, qualified expressions, membership tests, short circuit control forms, conditional expressions, and parenthesized expressions. A "potentially static expression function" is defined to be an expression function - whose expression is a potentially static expression; and - which contains no calls to itself; and - each of whose parameters (if any) is of mode IN and is of a static subtype; and - whose result subtype is a static subtype; and - to which no precondition or postcondition expression applies; and - which is not type invariant enforcing for any type (see 7.3.2); and - which is not a completion. The following language-defined representation aspect may be specified for a potentially static expression function. Static - The type of aspect Static is Boolean. A "static expression function" is defined to be an expression function whose Static aspect is True. In addition, an inherited function is defined to be a static expression function if the corresponding primitive function of the parent or progenitor type is a static expression function. [A static expression function is a static function; see 4.9]. In 7.3.2, add the following at the end of the Static semantics section. If one or more invariant expressions apply to a nonabstract type T, then a subprogram or entry is said to be "type invariant enforcing" for T if - it is the Read or Input stream-oriented attribute of the type T; or - it is declared within the immediate scope of T (or by an instance of a generic unit, and the generic is declared within the immediate scope of type T), and either: * has a result with a part of type T; or * has one or more *out* or *in out* parameters with a part of type T; or * has an access-to-object parameter or result whose designated type has a part of type T; or * is a procedure or entry that has an *in* parameter with a part of type T. - and either: * T is a private type or a private extension and the subprogram or entry is visible outside the immediate scope of type T or overrides an inherited operation that is visible outside the immediate scope of T; or * T is a record extension, and the subprogram or entry is a primitive operation visible outside the immediate scope of type T or overrides an inherited operation that is visible outside the immediate scope of T. Each such part of type T is said to be "subject to an invariant check" for T. In the Dynamic Semantics section, replace 7.3.2(15/4-20/5) with An invariant check is checked upon successful return from a call on any subprogram or entry which is type invariant enforcing for T. The check is performed on each part of type T which is subject to an invariant check for T. !discussion The stuff in 7.3.2 (type invariants) is all intended to be semantics-preserving. The only goal of this rearrangement is to define the term "type invariant enforcing" so that we can say that an expression function which is "type invariant enforcing" for some type T is not a potentially static expression function. And, of course, the term itself is subject to discussion - we might choose a different term. This version incorporates feedback from the last two meetings so that a) in order for an expression function to be a static function, you have to explicitly ask for it by specifying the Static aspect (a new Boolean aspect). b) an expression function which is a completion is never a static function. No view-specific stuff where sometimes it is and sometimes it isn't, depending on whether the completion is visible. c) an expression function which is subject to a type invariant is never a static function. !example !ASIS ** ASIS queries needed ** !ACATS test ACATS B-Tests and C-Tests. !appendix From: Jean-Pierre Rosen Sent: Tuesday, May 7, 2013 7:28 AM First asking, in case it has been discussed before... Wouldn't it be possible to make some expression functions static? Apparently, all that is needed is to add "formal parameters of an expression function" to the list of static things in 4.9. (Of course, the actual parameters of the call would have to be static, but that's already covered by 4.9(6)) **************************************************************** From: Randy Brukardt Sent: Tuesday, May 7, 2013 6:24 PM > First asking, in case it has been discussed before... > > Wouldn't it be possible to make some expression functions static? This was mentioned as a possible extension in the original AI. The !discussion section of AI05-0177-1 says: One could imagine allowing these functions (when visible) to be used in static expressions if the inlined expression would be static. This would definitely allow abstracting expressions that currently are written as a giant single expression because they need to be static. That's something you cannot do now. We didn't add this to proposal in order to keep the proposal simple. There's a bit of discussion of this in the e-mail, but nothing very interesting. I thought we also discussed it briefly at a meeting, but I didn't find anything in the October 2010 minutes when this was mainly discussed. > Apparently, all that is needed is to add "formal parameters of an > expression function" to the list of static things in 4.9. (Of course, > the actual parameters of the call would have to be static, but that's > already covered by 4.9(6)) I think it would be necessary for the fact that it is an expression function to be visible at the point of use. That would limit the value of this as it would prevent expression functions used as completions from participating. If we were willing to break privacy, we could allow expression functions used as completion in the private part, but that's probably a bad idea. Perhaps a better idea would be to have an aspect Static_Possible that could be applied to a subprogram declaration. The completion then would have to be an expression function that can be static. Also, I think there would have to be rule that for such a function the expression of it is static if one considers the parameters static. (And since not all types can be static, if there are any problems that aren't of either scalar or string types, then those parameters would be non-static.) And we'd need some sort of rule to deal with recursion (that's something we don't currently have to deal with in static expressions), unless we're willing to have compilers crash in such circumstances. (Running out of memory is hard to check for accurately, and it's often impossible to recover.) Anyway, this is a non-trivial idea. No problem with adding it as a possible Amendment, but it isn't going to magically appear as a Binding Interpretation in Ada 2012 (we already rejected that idea initially). **************************************************************** From: Robert Dewar Sent: Tuesday, May 7, 2013 6:38 PM > Anyway, this is a non-trivial idea. No problem with adding it as a > possible Amendment, but it isn't going to magically appear as a > Binding Interpretation in Ada 2012 (we already rejected that idea initially). Maybe we should try implementing Randy's pragma first, and see if there are unforseen difficulties. With that pragma, we don't even have to limit it to expression functions! **************************************************************** From: Steve Baird Sent: Wednesday, May 8, 2013 4:18 PM > Anyway, this is a non-trivial idea. No problem with adding it as a > possible Amendment, but it isn't going to magically appear as a > Binding Interpretation in Ada 2012 (we already rejected that idea initially). You got that right. We'd have to be careful not to ignore the subtypes of the formal parameters. When we "plug in" the arguments to see if the resulting expression is static, I think we'd need to treat the plugged-in value like a qualified expression, qualified by the subtype of the formal. There is also the question of ignored formal parameters. A particularly pathological example: package Pkg is type T is private with Invariant => Is_Even (T); function Is_Even (X : T) return Boolean; function Zoofle (X : in out T; Y, Z : Integer) return Integer is (Y + Z) with Static_Possible; private type T is new Integer; function Is_Even (X : T) return Boolean is (X mod 2 = 0); Invalid : T := 3; Three : constant Integer := Zoofle (Invalid, 1, 2); -- static? end Pkg; We'd probably deal with this particular case by just requiring formal parameters to be of mode In, but the point is that such a rule would need to be stated. I agree with Randy; this is not a one-liner. **************************************************************** From: Robert Dewar Sent: Wednesday, May 8, 2013 4:31 PM > We'd probably deal with this particular case by just requiring formal > parameters to be of mode In, but the point is that such a rule would > need to be stated. To me that's an OBVIOUS restriction for a static function **************************************************************** From: Steve Baird Sent: Wednesday, May 8, 2013 5:33 PM Interactions with short circuit evaluation, for example, might be less obvious. Flag_V1 : constant Boolean := True or else (1 / 0) = 123; is static, but presumably this version function Or_Else (C1, C2 : Boolean) return Boolean is (C1 or else C2) with Static_Possible; Flag_V2 : constant Boolean := Or_Else (True, (1 / 0) = 123); would not be static. My only real point is to agree with Randy: this is not a one-liner, if only because these "OBVIOUS" restrictions would need to be stated. **************************************************************** From: Robert Dewar Sent: Wednesday, May 8, 2013 5:56 PM > Flag_V2 : constant Boolean := Or_Else (True, (1 / 0) = 123); > > would not be static. I would not allow anything like this most certainly. All arguments to a function have to be static. Again that seems like an obvious restriction. (1 / 0) = 123 is not a static expression! > My only real point is to agree with Randy: this is not a one-liner, if > only because these "OBVIOUS" restrictions would need to be stated. The proper approach would be to make the restrictions as tight as possible, rather than getting into the tempting mode of making them as universal as possible. **************************************************************** From: Steve Baird Sent: Tuesday, August 25, 2015 4:06 PM Here is a first cut at an AI allowing calls to expression functions to occur in static expressions. This is part of my Madrid homework. [This was version /04 of the AI - Editor.] Many thanks to Randy for his helpful comments (but please do not take this to mean that Randy agrees with anything in this proposal). **************************************************************** From: Tucker Taft Sent: Monday, September 14, 2015 3:52 PM Looks good. I agree we probably don't want an attribute. **************************************************************** From: Steve Baird Sent: Saturday, September 17, 2015 11:20 PM !wording differences from previous version are highlighted. [This is version /04 of the AI - Editor.] The idea with this change is that a call to an expression function with static arguments which fails a check (during its compile time evaluation) is simply not a static expression, as opposed to being illegal. This addresses the compatibility issue that Randy raised. [But it doesn't address the original compatibility issue that Steve himself raised - Editor.] **************************************************************** From: Steve Baird Sent: Thursday, October 5, 2017 2:55 PM It seems clear that compatibility issues are a major concern associated with this proposal. We don't want examples which were previously legal to start running afoul of the "no check failures in a static expression" rule. Bob suggested one solution to this problem: an expression which fails the "no check failures" test becomes non-static, as opposed to illegal. But the consensus in Vienna (I am told) was that we also don't want to start allowing constructs which were previously illegal. There is a solution which satisfies both constraints, although I am not claiming that it is elegant: we relax the legality rules as per Bob's proposal but only in the case of a static expression that includes a call to an expression function. Such an expression could never currently be static, so this relaxation would not cause us to accept something that was previously rejected. So we would continue to disallow N : constant := 0; begin if N /= 0 then X := 10 / N; end if; but we would also continue to allow N : constant := 0; function Ratio (X : Integer) return Integer is (X / N); begin if N /= 0 then X := Ratio (10); end if; ==== I was tasked with assessing the compatibility impact of an earlier version of this proposal, trying to somehow figure out how often situations like procedure Foo is function Inc (X : integer) return Integer is (X + 1); subtype S is Integer range 0 .. Inc (3); Y : S := ... ; begin -- if S is a static subtype then this case stmt is illegal case Y is when 0 .. 33 => ...; when 44 .. 55 => ...; when others => ... ; end case; end; arise in practice. I didn't get this done. ==== There is the point mentioned in the !discussion section of this AI: 3) Do we need to say anything about type invariants? No, because if a function has a parameter (or result) of a private type, then it's not a static function. But what if it is completed as a static expression function after the private type is completed? Maybe we need a rule saying that if a type invariant applies to a function than the function is not a static expression function (like the rule already given for predicates). I think we do need this rule. The AI says A "static expression function" is defined to be an expression function - ...; and - ...; and - ...; and - ...; and - ... I think we need to invent a term for the property implicitly defined in the section on type invariants An invariant is checked upon successful return from any call on a subprogram or entry that ... Something like An entry or subprogram is said to be an "invariant boundary" entry or subprogram if ... followed by a use of the new term An invariant is check upon successful return from any call on an invariant boundary subprogram or entry. Then we can use the new term to add a new clause to the definition of "static expression function" along the lines of "which is not an invariant boundary subprogram; and" Other possible names for the new term: "invariant enforcing", "invariant checking". ==== Opinions? **************************************************************** From: Tucker Taft Sent: Thursday, October 5, 2017 3:16 PM > It seems clear that compatibility issues are a major concern > associated with this proposal. Maybe for some folks. Expression functions are pretty new! ... > There is a solution which satisfies both constraints, although I am > not claiming that it is elegant: we relax the legality rules as per > Bob's proposal but only in the case of a static expression that > includes a call to an expression function. Such an expression could > never currently be static, so this relaxation would not cause us to > accept something that was previously rejected. That seems fine to me. > ... > I think we need to invent a term for the property implicitly defined > in the section on type invariants > An invariant is checked upon successful return from any > call on a subprogram or entry that ... > > Something like > An entry or subprogram is said to be an "invariant > boundary" entry or subprogram if ... I would somewhat rather associate the notion of boundary with the type being defined, rather than this one particular aspect that is checked at the boundary. Perhaps simply "boundary subprogram for private type T" or "boundary subprogram for some partial view." Getting the word invariant there muddies the waters a bit for me. The concept of such a boundary exists even if no invariants have been defined explicitly. I suppose any term we pick would eventually grow on me... ;-) ... > Other possible names for the new term: "invariant enforcing", > "invariant checking". I find these names even muddier... I would like to describe the concept, without talking about what things might happen when crossing that border. Sort of like calling the border between two countries an "immigration control line." > ==== > > Opinions? See above. **************************************************************** From: Steve Baird Sent: Thursday, October 5, 2017 3:41 PM > I would somewhat rather associate the notion of boundary with the > type being defined, I like that idea too. IIRC, we have wanted a well-defined term for this for other reasons in the past. Would precisely defining the boundary for a type also help with the questions raised in AI12-0210 (Type Invariants and Generics)? It seems to me that the two issues are related. Roughly speaking, the idea we are trying to capture here is that a boundary subprogram for a given private type a) can see the implementation of the private type; and b) is callable from places that cannot see the implementation of the private type; and c) has a non-in-mode parameter or a function result of the type. Right? **************************************************************** From: Randy Brukardt Sent: Thursday, October 5, 2017 3:46 PM > > It seems clear that compatibility issues are a major concern > > associated with this proposal. > > Maybe for some folks. Expression functions are pretty new! Two points on this: (1) My experience is that once one has expression functions and is used to the idea, one tends to write everything possible as an expression function. (This is a problem if you are writing Ada 2005 ACATS tests or for a compiler that doesn't support them. I've done both. :-) (2) This compatibility problem exists any time a regular function is changed into an expression function or vice-versa. It's not just a one time thing. In particular, I expect Janus/Ada customers to rewrite regular functions into expression functions in some cases, because Janus/Ada only supports inlining on expression functions. When that is done, they'd be at risk of running into these compatibility issues. [Note to any Janus/Ada customers reading this: I'm speaking in the future tense here. :-)] ... > > There is a solution which satisfies both constraints, although I am > > not claiming that it is elegant: we relax the legality rules as per > > Bob's proposal but only in the case of a static expression that > > includes a call to an expression function. Such an expression could > > never currently be static, so this relaxation would not cause us to > > accept something that was previously rejected. > > That seems fine to me. Cool. I predicted to Steve the opposite. (It is a rather clunky rule, and I thought you'd object to the "bolted-on" look of it.) **************************************************************** From: Tucker Taft Sent: Thursday, October 5, 2017 6:42 PM > Roughly speaking, the idea we are trying to capture here is that a > boundary subprogram for a given private type > a) can see the implementation of the private type; and > b) is callable from places that cannot see the implementation > of the private type; and > c) has a non-in-mode parameter or a function result of the type. I don't understand why you have that last bullet in that form. Why does the mode matter? And are you considering access parameters or access results? From a SPARK point of view, you will still be presuming the invariant is true on entry, which you will not be doing for local functions. > Right? Modulo my complaint about (c) **************************************************************** From: Steve Baird Sent: Thursday, October 5, 2017 7:08 PM > I don't understand why you have that last bullet in that form. Why does the > mode matter? And are you considering access parameters or access results? > From a SPARK point of view, you will still be presuming the invariant is true > on entry, which you will not be doing for local functions. Good point about access parameters. And even for others, I see your point. There are advantages to ignoring the parameter mode completely (as opposed to special rules for in-mode non-access parameters) and I don't see any disadvantages, even if no runtime check is performed in that case. And of course when I talked about a parameter/result of the private type, I should have been talking about a parameter/result of a type that has a part which is of that type. **************************************************************** From: Tucker Taft Sent: Thursday, October 5, 2017 8:05 PM > Good point about access parameters. > > And even for others, I see your point. > > There are advantages to ignoring the parameter mode completely (as > opposed to special rules for in-mode non-access parameters) and I > don't see any disadvantages, even if no runtime check is performed in > that case. Right. This is another reason I would be reluctant to include the word "invariant" in the term we end up using. > And of course when I talked about a parameter/result of the private > type, I should have been talking about a parameter/result of a type > that has a part which is of that type. You could argue that boundary subprograms need not have any parameters or results of the type. The key point is that their body has more visibility on the type than their callers. They might be passed an access value and follow it three steps to an object of the private type, and do their thing there. SPARK as of today (prior to "safe" pointers) doesn't have this problem, but presumably in Ada we do have that situation, and SPARK with safe pointers might have it as well. So I think the parameter profile might be irrelevant once you start having pointers. But now if we bring this back to expression functions -- can they be static if they have any parameters of an access type? And I have lost track of what this whole thing was about -- why are invariant checks a problem? We don't want to do them as part of static evaluation? Why don't we say that a static expression function must not be the completion of a function declaration. Hence, if you want a function to be static, give the expression when it is declared. **************************************************************** From: Randy Brukardt Sent: Thursday, October 5, 2017 8:21 PM ... > But now if we bring this back to expression functions -- can they be > static if they have any parameters of an access type? > And I have lost track of what this whole thing was about -- why are > invariant checks a problem? From memory, we don't want any checks that might fail in a static function call. We disallow predicates, and Steve decided we needed to do the same for any invariant checks. Making the function visible without a completion doesn't completely eliminate the problem, as an invariant can be visibly defined and so can an expression function of a private type. Moreover, I already strongly dislike the fact that the implementation of a static function has to be exposed. It makes them go contrary to the basic point of Ada (a strong separation between specification and implementation). Making that problem worse doesn't improve the AI in my view. **************************************************************** From: Tucker Taft Sent: Thursday, October 5, 2017 9:43 PM This surprises me. What is the purpose of a static function if you don't know it is static and cannot use it as one? At least with this AI, the only way you know that an expression function is a static function is by looking at its defining expression. I suppose if there were an aspect "Static" or equivalent, then you could postpone the "body" of the expression function to the private part. Am I missing something? **************************************************************** From: Randy Brukardt Sent: Thursday, October 5, 2017 10:01 PM > This surprises me. What is the purpose of a static function if you > don't know it is static and cannot use it as one? One could argue "approximately the same as any other user-defined static function", but that's a discussion for a different time. ... > At least with this AI, the only way you know that an expression > function is a static function is by looking at its defining > expression. I suppose if there were an aspect "Static" or equivalent, > then you could postpone the "body" of the expression function to the > private part. Am I missing something? There surely should be a "Static_Possible" aspect, which among other things would allow deferring the expression elsewhere (probably not to a body, though, as the compiler has to be able to see a static expression that it is evaluating). It certainly would be needed should we ever try to expand static processing to user-defined static expressions. (Jeff told me privately that the UK would like to see static expression processing regularized. I think we've already rejected that idea for this cycle, but I think we need to leave the possibility open.) *************************************************************** From: Tucker Taft Sent: Thursday, October 5, 2017 10:57 PM > There surely should be a "Static_Possible" aspect, which among other > things would allow deferring the expression elsewhere (probably not to > a body, though, as the compiler has to be able to see a static > expression that it is evaluating). I am dubious. Static expressions can affect legality, so you really have to know what the function is computing. There really can't be any "abstraction" here to speak of. > It certainly would be needed should we ever try to expand static > processing to user-defined static expressions. (Jeff told me privately > that the UK would like to see static expression processing > regularized. I think we've already rejected that idea for this cycle, > but I think we need to leave the possibility open.) I think you are talking about a completely different AI than this one. Given the current AI, there seems no particular value to allowing a static expression function to be a completion. **************************************************************** From: Randy Brukardt Sent: Thursday, October 5, 2017 11:11 PM ... > I think you are talking about a completely different AI than this one. > Given the current AI, there seems no particular value to allowing a > static expression function to be a completion. Yes, a different (and future) AI. But I don't want this AI to prevent that AI from being possible. *************************************************************** From: Tucker Taft Sent: Thursday, October 5, 2017 11:04 PM > Yes, a different (and future) AI. But I don't want this AI to prevent > that AI from being possible. Right. But being *more* restrictive than absolutely necessary is our usual approach. By requiring static expression functions to be defined where they are declared, we are keeping this AI simpler, and allowing ourselves to relax the restrictions later. *************************************************************** From: Steve Baird Sent: Thursday, October 5, 2017 11:09 PM > And I have lost track of what this whole thing was about -- why are > invariant checks a problem? We don't want to do them as part of static > evaluation? Exactly. > Why don't we say that a static expression function must not be the > completion of a function declaration. Sounds like a nice clean solution; I like it. It is inconsistent with our treatment of deferred constants (because a use of a deferred constant can be static if the completion is visible), but that's ok I suppose. *************************************************************** From: Steve Baird Sent: Friday, October 6, 2017 11:26 AM > It is inconsistent with our treatment of deferred constants (because a > use of a deferred constant can be static if the completion is > visible), Do we decide whether an expression function is a static expression function when the function is declared or when it is used? Consider: package Pkg is type T is private; Dc : constant T; function Expr_Func return T is (Dc); private type T is new Integer; Dc : constant T := 0; Named_Number : constant := Expr_Func; -- legal? end; *************************************************************** From: Randy Brukardt Sent: Monday, October 9, 2017 7:07 PM >> There surely should be a "Static_Possible" aspect, which among other >> things would allow deferring the expression elsewhere (probably not >> to a body, though, as the compiler has to be able to see a static >> expression that it is evaluating). >I am dubious. Static expressions can affect legality, so you really >have to know what the function is computing. There really can't be any >"abstraction" here to speak of. The only reason to write a static function in the first place is to provide some "abstraction". Else it is just useless complication for the reader. If you are right here, then there shouldn't be any static functions to begin with. ... > >>> It certainly would be needed should we ever try to expand static > >>> processing to user-defined static expressions. (Jeff told me > >>> privately that the UK would like to see static expression > >>> processing regularized. I think we've already rejected that idea > >>> for this cycle, but I think we need to leave the possibility > >>> open.) > >> > >> I think you are talking about a completely different AI than this > >> one. Given the current AI, there seems no particular value to > >> allowing a static expression function to be a completion. > > > > Yes, a different (and future) AI. But I don't want this AI to > > prevent that AI from being possible. > > Right. But being *more* restrictive than absolutely necessary is our > usual approach. By requiring static expression functions to be > defined where they are declared, we are keeping this AI simpler, and > allowing ourselves to relax the restrictions later. Such a future AI would have to have a way (almost certainly an aspect) to mark completions that are static functions. (A "generalization" proposal that doesn't support private types is not really fixing anything, IMHO.) An AI that has some sort of automatic static functions is going to conflict with that future AI, as there would be a mismash of automatic and declared static functions, and probably conflicts in some cases. Automatic static functions is a dead-end that would pretty much prevent any further changes to static processing. *************************************************************** From: Tucker Taft Sent: Monday, October 9, 2017 8:45 PM >> Right. But being *more* restrictive than absolutely necessary is our >> usual approach. By requiring static expression functions to be >> defined where they are declared, we are keeping this AI simpler, and >> allowing ourselves to relax the restrictions later. > > Such a future AI would have to have a way (almost certainly an aspect) > to mark completions that are static functions. (A "generalization" > proposal that doesn't support private types is not really fixing > anything, IMHO.) An AI that has some sort of automatic static > functions is going to conflict with that future AI, as there would be > a mismash of automatic and declared static functions, and probably > conflicts in some cases. Automatic static functions is a dead-end that > would pretty much prevent any further changes to static processing. I could see adding an aspect to claim that something is a static function, and the compiler would check to be sure the expression then and there. We could provide a configuration pragma some day to make it automatic, I suppose. But I still don't get how you can complete a static function in a private part or a body, if it is going to be static outside the package as well. Because the *values* returned by the function can really matter to the caller, as they determine legality, and in some weird cases, can even determine the type (e.g. A'First(N) where "N" is a static expression function). Are you proposing that inside the package the function can be static, but not outside? I suppose I could see some value in that. I think that is how deferred constants work. But I was getting the impression you wanted the "I_Am_Static" aspect on the visible declaration of the function, but not provide the body there as well. That is what I don't understand... *************************************************************** From: Randy Brukardt Sent: Monday, October 9, 2017 9:21 PM ... > But I still don't get how you can complete a static function in a > private part or a body, if it is going to be static outside the > package as well. Because the *values* returned by the function can > really matter to the caller, as they determine legality, and in some > weird cases, can even determine the type (e.g. A'First(N) where "N" is > a static expression function). I don't get this obsession with values. The first thing an Ada programmer learns is to use names rather than literals. And I have to assume the desire to use expression functions in static expressions is to get more abstraction into the expression. Yes, the value can determine legality. But so what? If the function implements a sensible, well-documented abstraction, it will work fine without worrying about the exact value returned. If it doesn't, well, we can't legislate perfection. I doubt very much that you care about the values of expressions in your program unless the compiler rejects them. That certainly would be the case here. > But I was getting the impression you wanted the "I_Am_Static" > aspect on the visible declaration of the function, but not provide the > body there as well. That is what I don't understand... What about "abstraction" do you not understand?? Why you think these functions are somehow different than any other function ever written is what I don't understand. Any function someone writes might return a value other than one expected. Whether that makes the program illegal or just raises an exception doesn't change the response to it much. The programmer then has to look at the function body to see why an incorrect value was returned -- but that's the only time that one would look at the function body. If static expression functions aren't going to be used to provide abstraction, what else could they possibly be good for?? As I previously said, if they don't provide abstraction, then they aren't providing anything at all, and we should simply forget this idea. *************************************************************** From: Steve Baird Sent: Wednesday, January 5, 2018 6:43 PM Another iteration of this AI. [This is version /05 of this AI - ED.] We address all the compatibility issues by saying that you don't get a static expression function unless you ask for it by specifying a new aspect (named Static). [At some later date, we might consider defining a configuration pragma which says that the default value of the Static aspect of a potentially static expression function is True, not False. That's not currently part of this AI.] We address all the confusion associated with having a function sometimes be a static function and sometimes not (depending on whether the expression function completion is visible) by saying that an expression function which is a completion is never a static function. Thus, all views of a function agree on this point. We address the interactions with type invariants by making a textually large but semantically small change to type invariants (no change to type invariants except that we get a new term defined to identify a boundary subprogram). Feedback, as always, is appreciated. *************************************************************** From: Jeff Cousins Sent: Friday, January 12, 2018 7:15 AM Thanks Steve. "In 7.3.2, add the following at the end of the Static semantics section. If one or more invariant expressions apply to a nonabstract type T, then a subprogram or entry is said to be "type invariant enforcing" for T if - it is the Read or Input stream-oriented attribute of the type T; or" It seems strange to think of an attribute as a subprogram or entry – would attribute reference be better? You’ve lost the words added by AI12-0193 (i.e. "In the case of a call to a protected operation, the check is performed before the end of the protected action. In the case of a call to a task entry, the check is performed before the end of the rendezvous." *************************************************************** From: Tucker Taft Sent: Friday, January 12, 2018 11:27 AM ... > It seems strange to think of an attribute as a subprogram or entry – would > attribute reference be better? We use the terminology Steve is using in general. See the definition of 'Write, for example: "For every subtype S of a specific type T, the following attributes are defined. S'Write S'Write denotes a procedure with the following specification: ..." *************************************************************** From: Steve Baird Sent: Friday, January 12, 2018 12:27 PM > You’ve lost the words added by AI12-0193 (i.e. “In the case of a call > to a protected operation, the check is performed before the end of the > protected action. In the case of a call to a task entry, the check is > performed before the end of the rendezvous.” Good catch! I agree that we don't want to delete that sentence. The changes 7.3.2 are intended to introduce the definition of a new term and otherwise be semantics-preserving. ***************************************************************