CVS difference for ai05s/ai05-0144-1.txt

Differences between 1.7 and version 1.8
Log of other versions for file ai05s/ai05-0144-1.txt

--- ai05s/ai05-0144-1.txt	2010/01/09 01:31:29	1.7
+++ ai05s/ai05-0144-1.txt	2010/01/17 04:01:57	1.8
@@ -3110,3 +3110,1357 @@
 anything. :-)
 
 ****************************************************************
+
+From: Edmond Schonberg
+Sent: Thursday, March 12, 2009  10:12 AM
+
+> And by the way, what was the other topic?  The aspect specification
+> idea?  Conditional expressions and/or "implies"?  I can't remember.
+[Ed is replying to a message related to AI05-0138-1, and filed there.
+- Editor]
+
+Shouldn't it be in-out formals for functions?  The aspect specification is a
+syntactic issue that is non-controversial.  Conditional expressions are a
+completely unrelated topic that deserves its own discussion. And "implies" is
+shaping up like the third rail of ARG discussions so we should let it rest for
+now.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 12, 2009  12:08 PM
+
+I thought we had a specific topic we were supposed to discuss.  Perhaps this is
+in Randy's notes.  I am happy to talk about other things, but I don't want to
+preempt general ARG discussions on things that we weren't "assigned" to talk
+about in our subgroup. Also, we only have so much time, so we don't want to use
+it all up with things that were supposed to be someone else's responsibility.
+
+Randy, can you check the minutes?
+
+****************************************************************
+
+From: Bob Duff
+Sent: Thursday, March 12, 2009  10:31 AM
+
+According to Steve's original invitation, the other topic is:
+
+>> Although it is a completely unrelated issue, AI-123 (composability of
+>> equality) was also left crying on the doorstep of this august body,
+>> so we will be discussing that one too.
+
+Last time I looked at AI-123, it seemed to be getting too complicated for my
+taste, so I'm inclined to drop the idea, even though I was initially in favor.
+
+I agree with Ed that in-out formals for functions is worth discussing, since I
+see it as closely related to the anon access stuff.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Thursday, March 12, 2009  12:46 PM
+
+> And by the way, what was the other topic?
+
+I believe it was composition of equality (AI05-0123).
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 12, 2009  12:58 PM
+
+Ah, yes.  Not quite as momentous as these other issues, but worth some focused
+discussion.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 12, 2009  1:13 PM
+
+I don't see the point in talking about in-out formals for functions until we
+have a proposal for dealing with the ordering dependences they foster.  Randy
+chose to separate the AIs, but I don't personally want to discuss one without
+the other.  That is really the only tricky issue. Allowing in-out parameters in
+functions is trivial when ignoring the ordering issue.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 12, 2009  1:22 PM
+
+> Last time I looked at AI-123, it seemed to be getting too complicated
+> for my taste, so I'm inclined to drop the idea, even though I was
+> initially in favor.
+
+Well, that's what we need to discuss: is there rules that make sense that don't
+cause lots of unmitigated trouble?
+
+> I agree with Ed that in-out formals for functions is worth discussing,
+> since I see it as closely related to the anon access stuff.
+
+The trouble with that is that we can't do it until I've finished writing
+AI05-0144-1 and you all have had time to digest it. There is no semantic issues
+with "in out" parameters that need discussion (we did that last time) and the
+write-up in AI05-0143-1 covers everything that needs to be covered. The only
+topic of interest is about adding visibility to/preventing bad side effects in
+calls. That's what AI05-0144-1 is about; I'm surveying the possibilities and
+proposing possible solutions (in detail, because that is the only way to
+evaluate them).
+
+(There's also some Ada-Comment threads that are relevant.)
+
+It would be a waste of everyone's time to re-invent this stuff given I've
+already worked out most of the details (and there are a *lot* of details to work
+out), just haven't had time to write them all down.
+
+I would have to work all weekend to get anywhere near having that done on top of
+all of the other things that need to be handled by the conference call on
+Thursday. That would be on top of doing that the last couple of weekends already
+-- I don't honestly see the rush. I was expecting to give this stuff an
+appropriate discussion in Brest.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 12, 2009  1:25 PM
+
+> I don't see the point in talking about in-out formals for functions
+> until we have a proposal for dealing with the ordering dependences
+> they foster.  Randy chose to separate the AIs, but I don't personally
+> want to discuss one without the other.  That is really the only tricky
+> issue.
+> Allowing in-out parameters in functions is trivial when ignoring the
+> ordering issue.
+
+Must be something wrong here, I'm actually agreeing with Tucker on an "in out"
+parameter for functions issue. But I am. You can read the first half of that
+proposal in AI05-0144-1, but it stops just as I get to the good part...
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Thursday, March 12, 2009  4:24 PM
+
+I don't see any reason to worry about ordering issues. People have no excuse for
+writing cases where ordering is important and if they do, non-deterministic
+ordering is typical of Ada behavior and is fine.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 12, 2009  5:05 PM
+
+I agree with you vis-a-vis *intentionally* writing code that depends on ordering
+issues; the question is whether to provide help to prevent *unintentionally*
+write such code. For the current language, any such dependencies have to be in a
+single parameter list, so it's pretty hard to imagine it happening
+unintentionally. But once we add "in out" parameters for functions, the issue
+becomes much more likely. Consider:
+
+      B := F(A) + F(A);
+
+If F has an "in out" parameter (or an access parameter, for that matter), this
+might (or might not, depending on the way parameters are passed and other
+factors) have an ordering dependency. If F only has an "in" parameter, it does
+not have an ordering dependency (unless F has a dangerous side-effect, not
+really preventable).
+
+If we could detect cases that are really likely to be problems without detecting
+too many cases that aren't problems (a tall order, I realize), that would make
+Ada safer and more predictable with (hopefully) little compatibility cost.
+
+Given that this issue is the primary reason that Tucker and others have been
+resisting "in out" parameters for functions for many years, we at the very least
+owe them an attempt to address the problem before telling them to go away and
+stop worrying. :-)
+
+****************************************************************
+
+From: Bob Duff
+Sent: Thursday, March 12, 2009  5:43 PM
+
+...
+> > I don't see any reason to worry about ordering issues. People have
+> > no excuse for writing cases where ordering is important and if they
+> > do, non-deterministic ordering is typical of Ada behavior and is
+> > fine.
+
+I agree with Robert on this.
+
+...
+> If we could detect cases that are really likely to be problems without
+> detecting too many cases that aren't problems (a tall order, I
+> realize), that would make Ada safer and more predictable with
+> (hopefully) little compatibility cost.
+>
+> Given that this issue is the primary reason that Tucker and others
+> have been resisting "in out" parameters for functions for many years,
+> we at the very least owe them an attempt to address the problem before
+> telling them to go away and stop worrying. :-)
+
+If we can find a way to eliminate ordering problems, or make them clearer in the
+source code, that's great.  But if we can't, I don't see how that should prevent
+'in out' params on functions.
+
+Functions can have side effects on globals, and on stuff accessible via access
+values passed to them.  Sad.  But I don't see how 'in out' makes it any worse.
+
+You're telling me I can't write:
+
+    Foo : constant T := F(A);
+
+because I might accidentally write:
+
+    B := F(A) + F(A);
+
+Humph.
+
+Anyway, "F(A) + F(A)" seems more obviously a problem than "F + F", where F is a
+function call modifying global A.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Thursday, March 12, 2009  6:09 PM
+
+>> I agree with you vis-a-vis *intentionally* writing code that depends
+>> on ordering issues; the question is whether to provide help to
+>> prevent
+>> *unintentionally* write such code. For the current language, any such
+>> dependencies have to be in a single parameter list, so it's pretty
+>> hard to imagine it happening unintentionally. But once we add "in
+>> out" parameters for functions, the issue becomes much more likely. Consider:
+>>
+>>       B := F(A) + F(A);
+>>
+>> If F has an "in out" parameter (or an access parameter, for that
+>> matter), this might (or might not, depending on the way parameters
+>> are passed and other factors) have an ordering dependency. If F only
+>> has an "in" parameter, it does not have an ordering dependency
+>> (unless F has a dangerous side-effect, not really preventable).
+
+I don't think this is a concern at all. If a compiler or other static analysis
+tool wants to provide help that's fine, but we should not entangle legality
+issues. Note that a sophisticated analysis tool could warn about dangerous
+side-effects :-)
+
+Right now, this has well defined non-deterministic semantics.
+If F modifies a global, the ordering problem is there now, and in fact much
+worse, because it is more invisible.
+
+The semantics in this case is order left to right or right to left. It is
+actually rather difficult to see how it could make a differnece in this case
+(addition being commutative you know :-)
+
+Let's not let this get in the way, to my mind, there is nothing new here,
+expressions can have side effects, e.g. if you write
+
+    B := F(G) + H;
+
+and F(G) increments H, then you can get one of two values. Actually to my mind
+Ada already OVER-constrains ordering, I don't like that
+
+      function F (X : Integer) return Integer is
+      begin GG := GG + 1; return X; end;
+
+      function G (X : Integer) return Integer is
+      begin FF : = FF + 1; return X; end;
+
+      FF, GG : Integer := 3;
+
+      ...
+
+      B := F(FF) + G(GG);
+
+is required to return 7, and is well defined :-).
+I think it should be allowed to return 6, using the evaluation scheme
+
+     Temp1 := FF;
+     Temp2 := GG;
+     Temp3 := F(Temp1);
+     Temp4 := G(Temp2);
+     Result := Temp3+Temp4;
+
+But this is disallowed by the language.
+
+I bet compilers sometimes get this wrong :-)
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 12, 2009  6:26 PM
+
+...
+> Functions can have side effects on globals, and on stuff accessible
+> via access values passed to them.  Sad.  But I don't see how 'in out'
+> makes it any worse.
+>
+> You're telling me I can't write:
+>
+>     Foo : constant T := F(A);
+>
+> because I might accidentally write:
+>
+>     B := F(A) + F(A);
+>
+> Humph.
+
+That's why it is the way it is currently (at least based on my discussions with
+Tucker).
+
+What I am investigating is rules that would leave the second illegal but allow
+the first, which puts the penalty where it belongs (on the dicey expressions).
+You could always introduce temporaries if needed. If that's what it takes to get
+consensus on "in out", I'm all for it.
+
+> Anyway, "F(A) + F(A)" seems more obviously a problem than "F
+> + F", where F is a function call modifying global A.
+
+Well, I would have preferred a language with either strict left-to-right
+evaluation or with rules making expressions with more than one function with
+side effects illegal. Surely my Ada-like language (if you can have a
+hypothetical language of your own, so can I :-) would have such a feature
+(probably built around strict, side-effect free functions). But that's
+certainly too incompatible for Ada (it wouldn't have been if the original
+function vs. value-returning procedure idea had stayed in Ada originally,
+but I recognize that no one understood the benefits back then, because all
+practical languages were full of unchecked stuff -- and it's not clear that
+that many do today, either.)
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Thursday, March 12, 2009  6:36 PM
+
+...
+> What I am investigating is rules that would leave the second illegal
+> but allow the first, which puts the penalty where it belongs (on the
+> dicey expressions). You could always introduce temporaries if needed.
+> If that's what it takes to get consensus on "in out", I'm all for it.
+>
+>> Anyway, "F(A) + F(A)" seems more obviously a problem than "F
+>> + F", where F is a function call modifying global A.
+
+I disagree that F(A) + F(A) is a problem
+
+For example,  Random (Generator) + Random (Generator);
+
+makes 100% good sense, even if Generator is updated by the function
+call. Pleae don't figure out complciated rules that are just a problem
+
+The next paragraph is of course irrelevant to our discussion, we are
+indeed talking about Ada, not Randy's preferred language (which
+incidentally for my taste is inferior to Ada in this department,
+but we really need not argue over other languages than Ada, we have
+a big enough job with just Ada on our hands).
+>
+> Well, I would have preferred a language with either strict left-to-right
+> evaluation or with rules making expressions with more than one function with
+> side effects illegal. Surely my Ada-like language (if you can have a
+> hypothetical language of your own, so can I :-) would have such a feature
+> (probably built around strict, side-effect free functions). But that's
+> certainly too incompatible for Ada (it wouldn't have been if the original
+> function vs. value-returning procedure idea had stayed in Ada originally,
+> but I recognize that no one understood the benefits back then, because all
+> practical languages were full of unchecked stuff -- and it's not clear that
+> that many do today, either.)
+
+Nothing has changed in our understanding or the input to the discussion.
+I know perfectly well the alledged benefits of such a design, they were
+alledged in the original Ada 83 design and soundly rejected. Nothing has
+changed to reconsider that decision. Doesn't mean you would have liked
+it then or now, but it does mean it is probably a waste of time to
+discuss it now in this thread. Just because people disagree with you
+does not mean they don't understand your point of view, just that they
+disagree with your conclusion.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 12, 2009  7:27 PM
+
+...
+> I disagree that F(A) + F(A) is a problem
+>
+> For example,  Random (Generator) + Random (Generator);
+>
+> makes 100% good sense, even if Generator is updated by the function
+> call. Pleae don't figure out complciated rules that are just a problem
+
+Well, there is a significant minority of Ada people who have used examples like
+this to keep "in out" parameters on functions out of the language. And they will
+continue to do that unless we make some effort to cut the gordian knot. Saying
+that it is "not a problem" is not going to be helpful in that way.
+
+How would *you* cut the gordian knot here? After all, we need to build consensus
+with people who disagree with your opinions on this topic.
+
+[For the record, I mostly agree with you that there is no strong need to provide
+additional checking; we're already deeply intangled in a morass and that isn't
+going change significantly either way. But I'm more interested in progress here
+rather than standing ones ground and playying tug-of-war.]
+
+...
+> Nothing has changed in our understanding or the input to the discussion.
+> I know perfectly well the alledged benefits of such a design, they
+> were alledged in the original Ada 83 design and soundly rejected.
+> Nothing has changed to reconsider that decision.
+
+Given that 25 years have passed, it is a mighty stretch to say that nothing has
+changed. The requirements for safety, security, static check, etc. have all
+become far more important, and far more processing power is available to the
+compiler. If you had asked me 20 years ago about that idea, I surely would have
+soundly rejected it then.
+
+Indeed, you could make exactly the same argument about "in out" parameters for
+functions. It was clear from day one of my use of Ada (1979) that this omission
+was very limiting - I doubt that there was that much experience. Yet it was not
+in Ada 80 or Ada 83. I actually argued against changing it in Ada 95, feeling
+that we had gotten this far without it (and probably falling victim to the
+fallacy that anonymous access types were good for anything). Obviously, my
+experience with O-O programming (esp. with Claw) showed me that I was wrong.
+
+Anyway, my point is that nothing significant has changed on the "in out"
+parameter - the level of the problem hasn't changed since day one with Ada. So
+why should we reconsider that particular idea (which you like) and not another
+(which you don't like)?
+
+> Doesn't mean you would have liked
+> it then or now, but it does mean it is probably a waste of time to
+> discuss it now in this thread. Just because people disagree with you
+> does not mean they don't understand your point of view, just that they
+> disagree with your conclusion.
+
+No one can disagree with my conclusion, because I haven't made one yet! (Not for
+Ada, anyway, which is all that really matter, right?) I'm mostly interested in
+surveying what is possible in this area, so that we have a clear idea of what we
+can and cannot do. That includes looking at ideas that are almost certainly
+going to be too incompatible. And, honestly, I'm not really interested in
+discussing it here until I'm done writing that survey up and have a firm
+proposal or two to discuss. Until that point, it is purely speculation as to
+what form a proposal will take.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Thursday, March 12, 2009  7:13 PM
+
+...
+> I disagree that F(A) + F(A) is a problem
+>
+> For example,  Random (Generator) + Random (Generator);
+>
+> makes 100% good sense, even if Generator is updated by the function
+> call...
+
+Now I'm confused as to your position.  The above works fine if the rule is
+"either order but not interleaved", as it is in Ada, but your previous message
+(about 7 versus 6) indicated that you would prefer to allow interleaved (or
+parallel?)  execution of the subexpressions.  If you interleave the evaluation
+of Random, you could get chaos here.  Likewise for:
+
+    P(F(...), G(...));
+
+where F and G do "new ...".
+
+> The next paragraph is of course irrelevant to our discussion, we are
+> indeed talking about Ada, not Randy's preferred language (which
+
+Randy's just poking fun at me for having a vaporware hobby language in my mind.
+Yes, it's irrelevant.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Thursday, March 12, 2009  7:43 PM
+
+> How would *you* cut the gordian knot here? After all, we need to build
+> consensus with people who disagree with your opinions on this topic.
+
+I think any attempt to somehow restrict side effects is misguided in the Ada
+context, I see no way of doing this in a consistent manner.
+
+And furthermore, since we can't deal with the dangerous unobvious case, why try
+so hard to deal with the less dangerous (because more obvious) case.
+
+> Given that 25 years have passed, it is a mighty stretch to say that
+> nothing has changed. The requirements for safety, security, static
+> check, etc. have all become far more important, and far more
+> processing power is available to the compiler. If you had asked me 20
+> years ago about that idea, I surely would have soundly rejected it then.
+
+This has nothing to do with processing power or requirements for safety and
+security. The proper way to handle the latter is to propose reasonable
+restrictions that remove what you consider the dangerous cases, then individual
+programmers can decide whether it's a good idea. Trying to retrofit this
+unconditionally is obviously out of the question in Ada, so the argument is only
+about your favoirte invented language, and that's not worth arguing about here
+
+> Indeed, you could make exactly the same argument about "in out"
+> parameters for functions. It was clear from day one of my use of Ada
+> (1979) that this omission was very limiting - I doubt that there was that much experience.
+
+I would have found a design along the lines you wanted to be dysfunctional, and
+I still would. I might of course make use of some restriction you proposed but I
+doubt it. Anyway, I suspect the only way of introducing things at this stage,
+including dealing with perceived problems in evaluation order caused by IN OUT
+parameters (I say perceieved, because after all we can always kludge with access
+junk to get exactly the same effect, and no one has got upset about that).
+
+> Yet it was not in Ada 80 or Ada 83. I actually argued against changing
+> it in Ada 95, feeling that we had gotten this far without it (and
+> probably falling victim to the fallacy that anonymous access types were good for anything).
+> Obviously, my experience with O-O programming (esp. with Claw) showed
+> me that I was wrong.
+
+You think you were wrong, but there is no general consensus, I think you were
+right. I guess if you find that this causes you to make errors in your
+programming, you can reasonably think about a restriction, but that is not a
+basis of reducing the expressive capability of the language.
+
+> Anyway, my point is that nothing significant has changed on the "in out"
+> parameter - the level of the problem hasn't changed since day one with Ada.
+> So why should we reconsider that particular idea (which you like) and
+> not another (which you don't like)?
+
+Because it has always been a severe restriction in the use of Ada. I gave the
+example of the random number generator in the defined Ada run-time, which cannot
+reasonably be implemented in Ada as defined today, that's unfortunate.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Thursday, March 12, 2009  7:47 PM
+
+>> I disagree that F(A) + F(A) is a problem
+>>
+>> For example,  Random (Generator) + Random (Generator);
+>>
+>> makes 100% good sense, even if Generator is updated by the function
+>> call...
+>
+> Now I'm confused as to your position.  The above works fine if the
+> rule is "either order but not interleaved", as it is in Ada,
+
+Yes, as you say "as it is in Ada", so the above diction is fine in Ada, and
+there is no reason to reject it.
+
+> but your previous message
+> (about 7 versus 6) indicated that you would prefer to allow
+> interleaved (or
+> parallel?)  execution of the subexpressions.
+
+I would not allow interleaving of bodies of function calls I would not go for
+collateral (parallel) evaluation, a la Algol-68 I would allow evaluating the
+tree in any order, that still works in this particular case. But in any case
+that is not something we are going to change now, Ada does require clear
+non-determinisitc R2L or L2R order and that's that.
+
+> If you interleave the evaluation
+> of Random, you could get chaos here.  Likewise for:
+>
+>     P(F(...), G(...));
+>
+> where F and G do "new ...".
+
+Again, I would not interleave at the body level, the above tree has two function
+calls. I would prefer you could interleave the evaluation of arguments to F and
+G in any order, but that would indeed raise issues with IN OUT, and in any case
+I am not suggesting this change.
+
+Given we have strict left-to-right or right-to-left ordering, and that is not up
+for discussion to change that, sorry for introducing that red herring, I see no
+danger in introducing IN OUT params for functions.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 12, 2009  9:56 PM
+
+>>> I don't see any reason to worry about ordering issues. People have
+>>> no excuse for writing cases where ordering is important and if they
+>>> do, non-deterministic ordering is typical of Ada behavior and is
+>>> fine.
+>
+> I agree with Robert on this.
+
+I understand these views, but I respectfully disagree.  I have used C a lot, and
+when it is easy to have expressions like "i++" and "(x = blah)" in the middle of
+statements, the likelihood of getting hit with order-of-evaluation problems
+rises dramatically.  Of course these problems are possible today in Ada, but I
+believe strongly that if functions have OUT parameters, these problems will
+become significantly more of an issue for "typical" programmers writing typical
+programs.
+
+Pascal, Randy, and I reached what I thought was a compromise on this
+long-standing battle, where we would support adding IN-OUT parameters to
+functions as part of adding some rules to minimize the likelihood of
+order-of-evaluation problems.  My fervent hope is that Randy at least remembers
+this bargain.
+
+I don't think the rules need to be foolproof. Reasonably straightforward rules
+should catch the large majority of problems.  But if we don't define the rules
+at the same time as we add OUT parameters for functions, there is no way we
+could add them in later due to compatibility concerns.
+
+Here is a possible rule:
+
+    Given an actual parameter of a function call
+    whose corresponding formal is of mode OUT or IN OUT,
+    if the parameter denotes or is a view conversion
+    of a variable of type T, then no second name
+    within an expression, simple statement,
+    object declaration, type declaration, or generic
+    instantiation containing the call shall denote a
+    variable of type T unless the name denoting the
+    parameter and the second name are *statically
+    distinct* names.
+
+A definition of "statically distinct" would have to occur here, or perhaps in
+4.9 (where "statically denote" is defined):
+
+    Two names are *statically distinct* if they statically
+    denote different declarations.  Further, two object names
+    are statically distinct if they denote objects of the same
+    type, but one name is an indexed_component while the other
+    is a selected_component, or both names are selected_components
+    and they denote distinct component declarations of the same type.
+    Finally, two names are statically distinct if the first name
+    or some prefix of the first name is statically distinct
+    from the second name or some prefix of the second name,
+    and neither name contains a dereference.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 12, 2009  10:09 PM
+
+...
+> I don't think the rules need to be foolproof. Reasonably
+> straightforward rules should catch the large majority of problems.
+> But if we don't define the rules at the same time as we add OUT
+> parameters for functions, there is no way we could add them in later
+> due to compatibility concerns.
+>
+> Here is a possible rule:
+>
+>     Given an actual parameter of a function call
+>     whose corresponding formal is of mode OUT or IN OUT,
+>     if the parameter denotes or is a view conversion
+>     of a variable of type T, then no second name
+>     within an expression, simple statement,
+>     object declaration, type declaration, or generic
+>     instantiation containing the call shall denote a
+>     variable of type T unless the name denoting the
+>     parameter and the second name are *statically
+>     distinct* names.
+
+I used "potentially the same object" for this purpose. I hadn't defined what
+"potentially the same object" meant, yet.
+
+BTW, the above is quite a bit stronger than necessary, because of the order
+implicit in assignment statements and calls (for instance, you have to evaluate
+all of the parameters to a call before you can make it, and none of those
+parameters can be modified until after that call; similarly, the target of an
+assignment can't be modified until after the source expression is evaluated). As
+long as any modifications have to happen after any reads, the expression cannot
+be order-dependent. There is a fairly easy way to describe that (you do have to
+talk about sub-expressions).
+
+Read the part of AI-144 that I did write to see how this works.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 12, 2009  10:11 PM
+
+>> How would *you* cut the gordian knot here? After all, we need to
+>> build consensus with people who disagree with your opinions on this topic.
+>
+> I think any attempt to somehow restrict side effects is misguided in
+> the Ada context, I see no way of doing this in a consistent manner.
+>
+> And furthermore, since we can't deal with the dangerous unobvious
+> case, why try so hard to deal with the less dangerous (because more
+> obvious) case.
+
+I wrote a rather long answer to this question, which I believe made it into the
+Ada 95 AI on in-out parameters for functions, which was ultimately categorized
+as "no action."  I believe it is worth reading.
+
+The executive summary is that the side-effects are of a different nature.  If a
+function has internal, hidden side-effects, then it is the implementor of the
+abstraction who is responsible for making sure that order of evaluation doesn't
+matter (e.g. for things like Random or caching or memo-izing functions), and
+they must deal with the challenges of aliasing, if that is possible.
+
+When you have IN OUT parameters, it is the caller's responsibility, and the
+implementor of the abstraction has made no particular effort to worry about
+keeping things meaningful independent of order of evaluation.  The caller has to
+worry about the order of evaluation, copy-out vs. by-reference, aliasing, etc.
+
+You can argue about which of these is more dangerous, but I think it is pretty
+clear that they are different sorts of problems, and the IN OUT function
+parameters are clearly a new problem that users haven't had to deal with before
+in Ada.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 12, 2009  10:45 PM
+
+...
+> I used "potentially the same object" for this purpose. I hadn't
+> defined what "potentially the same object" meant, yet.
+
+I think you have to talk about *names* not objects.  Objects are run-time
+entities, so it is pretty hard to have compile-time rules that depend on whether
+they overlap.
+
+> BTW, the above is quite a bit stronger than necessary, because of the
+> order implicit in assignment statements and calls (for instance, you
+> have to evaluate all of the parameters to a call before you can make
+> it, and none of those parameters can be modified until after that
+> call; similarly, the target of an assignment can't be modified until
+> after the source expression is evaluated). As long as any
+> modifications have to happen after any reads, the expression cannot be
+> order-dependent. There is a fairly easy way to describe that (you do have to talk about sub-expressions).
+
+I don't think the added complexity is worth it.  Assignments can still be a
+problem in various ways.  For example, if the LHS appears as an in-out parameter
+in a call within the RHS, it is not clear whether the assignment or the copy-out
+would happen first:
+
+    X := Post_Inc(X) * 2 + X;
+
+What is the final value of X, presuming Post_Inc returns the original value of
+its in-out parameter, but as a side-effect adds one to it?  Could the copy-out
+happen after the assignment to the LHS?  I'm not sure.  Until now we haven't had
+to be too specific about when exactly copy-out occurs (see 6.4.1(17) -- all it
+says is "after leaving the subprogram" and allows various things to happen in an
+"arbitrary order").
+
+More typical is the old array copy situation:
+
+    A(I) := B(Post_Inc(I));
+
+What value of I is used to index into A?
+
+There is enough uncertainty that I strongly feel we should outlaw having other
+uses of the variable in the same simple statement/expression where the variable
+is passed as an IN-OUT parameter to a function call.
+
+I really don't think it will be a burden on the programmer, since I think what
+people *really* want is to be able to write very simple expressions, containing
+a single function call with one or two OUT parameters, such as:
+
+    while Get_Next(Iterator, Element) loop
+        Put(Element);
+    end loop;
+
+Disallowing other appearances of "Iterator" or "Element" in an expression or
+simple statement containing a call on Get_Next(Iterator, Element) seems pretty
+reasonable.
+
+> Read the part of AI-144 that I did write to see how this works.
+
+I have read it once.  I'll take another look.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 12, 2009  10:47 PM
+
+...
+> You can argue about which of these is more dangerous, but I think it
+> is pretty clear that they are different sorts of problems, and the IN
+> OUT function parameters are clearly a new problem that users haven't
+> had to deal with before in Ada.
+
+Well, the problem of "visible side-effects" (giving it a name here to simplify
+the discussion) is definitely not quite the same as the one of hidden
+side-effects. One thing I learned while working on the half of AI-144 that I've
+already written is that it is very difficult to write an example of an
+expression with "visible side-effects" in Ada 2005 without using any access
+types: it's only possible with a procedure with multiple "in out" (or "out";
+I'll only talk about "in out" but consider "out" as well) parameters of related
+types (one parameters is a visible part of another). That pattern is so obvious
+that it's unlikely to occur by accident (it would require a single procedure
+with many parameters to them far enough apart to miss the problem).
+
+Once you have functions with "in out" parameters, the possibilities are endless
+(although those all boil down to a single pattern, which makes it relatively
+easy to craft a rule to check for them). You can add lots and lots of function
+calls; I've seen expressions that more than filled an entire page. To discover
+an order dependency in that is not going to be practical.
+
+So I've gained some sympathy for Tucker's position; if a rule to make visible
+side-effects illegal can be crafted that is reasonably simple and doesn't reject
+too many legitimate expressions than I think we should have it. It surely
+doesn't hurt to try. But I definitely want to avoid another accessibility-like
+set of rules that prevents as many legitimate calls as bad ones (because that
+would be a continual annoyance, even if the workaround is easy).
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 12, 2009  10:56 PM
+
+>> And furthermore, since we can't deal with the dangerous unobvious
+>> case, why try so hard to deal with the less dangerous (because more
+>> obvious) case.
+>
+> I wrote a rather long answer to this question, which I believe made it
+> into the Ada 95 AI on in-out parameters for functions, which was
+> ultimately categorized as "no action."  I believe it is worth reading.
+
+It is in AI95-00323, in the !appendix, in a comment dated Saturday, January 21, 2006  7:15 PM
+
+Here is a link to the AI:
+
+   http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ais/ai-00323.txt?rev=1.5
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, March 13, 2009 12:07 AM
+
+>> I used "potentially the same object" for this purpose. I hadn't
+>> defined what "potentially the same object" meant, yet.
+
+>I think you have to talk about *names* not objects.  Objects are
+>run-time entities, so it is pretty hard to have compile-time rules that
+>depend on whether they overlap.
+
+I used "object" because I wanted (in at least some versions) to be able to talk
+about designated objects, parts of objects, and the like. Perhaps "name" will be
+sufficient, but I didn't get that far yet. It might turn out better to change
+this term ultimately, depending on what the rule is.
+
+...
+> > BTW, the above is quite a bit stronger than necessary, because of
+> > the order implicit in assignment statements and calls (for instance,
+> > you have to evaluate all of the parameters to a call before you can
+> > make it, and none of those parameters can be modified until after
+> > that call; similarly, the target of an assignment can't be modified
+> > until after the source expression is evaluated). As long as any
+> > modifications have to happen after any reads, the expression cannot
+> > be order-dependent. There is a fairly easy way to describe
+>> that (you do have to talk about sub-expressions).
+>
+> I don't think the added complexity is worth it.  Assignments can still
+> be a problem in various ways.  For example, if the LHS appears as an
+> in-out parameter in a call within the RHS, it is not clear whether the
+> assignment or the copy-out would happen first:
+>
+>     X := Post_Inc(X) * 2 + X;
+
+I believe this is illegal by the proposed rule: there is a more nested
+modification of X and a less nested X. (Indeed, "Post_Inc(X) * 2 + X" would be
+illegal by itself in any scheme; I presume you meant something like:
+
+    X := Post_Inc(X) * 2; in which the assignment alone has a problem.)
+
+An assignment would be treated the same as a procedure call with two parameters
+for the purposes of this rule. (Note that I included all calls in the rule, both
+procedures and functions, and all kinds of functions, at least for development
+purposes -- that also makes it easier to see the bad case.)
+
+The only way to have a problem is to have a *more* nested modification and a use
+in different parameter of a call that includes the nested modification. So
+that's the only case that needs to be detected. (Remember that an operator is a
+function call, so it always is included.)
+
+...
+> I really don't think it will be a burden on the programmer, since I
+> think what people *really* want is to be able to write very simple
+> expressions, containing a single function call with one or two OUT
+> parameters, such as:
+>
+>     while Get_Next(Iterator, Element) loop
+>         Put(Element);
+>     end loop;
+
+A case that would be allowed by the proposed rule would be something like (using
+a Claw example):
+
+    Value := Get_Integer (Edit_Box, Width => Length(Edit_Box)/10);
+
+(Length is a function with only In parameters; Get_Integer has an In Out
+parameters.)
+
+This sort of thing happens often in O-O code, and I didn't want to make anything
+reasonable illegal that is in fact well-defined.
+
+It also clearly explains why procedure calls don't need to be illegal by a rule
+like this, which I find very important. I don't see any justification for
+treating them differently at the semantic level (although pragmatically, we may
+want to adopt a hole for compatibility reasons).
+
+****************************************************************
+
+From: Bob Duff
+Sent: Friday, March 13, 2009  6:30 AM
+
+> Here is a possible rule:
+>
+>     Given an actual parameter of a function call
+>     whose corresponding formal is of mode OUT or IN OUT,
+>     if the parameter denotes or is a view conversion
+>     of a variable of type T, then no second name
+>     within an expression, simple statement,
+>     object declaration, type declaration, or generic
+>     instantiation containing the call shall denote a
+>     variable of type T unless the name denoting the
+>     parameter and the second name are *statically
+>     distinct* names.
+
+If this sort of rule makes you happier, then I have no objection, and we can
+agree to disagree on whether or not the sky will fall without it.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Friday, March 13, 2009  6:58 AM
+
+...
+> If this sort of rule makes you happier, then I have no objection, and
+> we can agree to disagree on whether or not the sky will fall without
+> it.
+
+However, I think it would be very helpful to have some syntax to mark '[in] out'
+parameters at the call site.  That seems more important to me than forbidding
+the "bad" cases, but we could do both.
+
+If we had that, I would want a configuration pragma or other option to require
+such marks.  If that's not in the language, I would probably do it in GNAT as an
+impl-def pragma or something.  Maybe a Restriction.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Friday, March 13, 2009  8:32 AM
+
+> Pascal, Randy, and I reached what I thought was a compromise on this
+> long-standing battle, where we would support adding IN-OUT parameters
+> to functions as part of adding some rules to minimize the likelihood
+> of order-of-evaluation problems.  My fervent hope is that Randy at
+> least remembers this bargain.
+
+It's a bad bargain, it will just create situations where inappropriate rules
+stand in the way of reasonable use (like my random example).
+
+If you think such a restriction is useful, then add it as a restriction, and
+those, like you, who find this restriction useful can include it in your coding
+standard.
+
+> I don't think the rules need to be foolproof. Reasonably
+> straightforward rules should catch the large majority of problems.
+> But if we don't define the rules at the same time as we add OUT
+> parameters for functions, there is no way we could add them in later
+> due to compatibility concerns.
+>
+> Here is a possible rule:
+>
+>     Given an actual parameter of a function call
+>     whose corresponding formal is of mode OUT or IN OUT,
+>     if the parameter denotes or is a view conversion
+>     of a variable of type T, then no second name
+>     within an expression, simple statement,
+>     object declaration, type declaration, or generic
+>     instantiation containing the call shall denote a
+>     variable of type T unless the name denoting the
+>     parameter and the second name are *statically
+>     distinct* names.
+
+That would rule out the random example, I have lots of similar examples in mind!
+
+I don't mind this rule, but I think it should be a restriction
+
+    pragma Restriction (No_Explicit_Side_Effects);
+
+or something like that.
+
+For me, there will be endless cases where this is not a useful restriction, and
+I will not use this restriction.
+
+    F (A, A'Size)
+
+Seems a perfectly reasonable call to me where A is IN OUT. But as far as I can
+understand, would be ruled out by the rule above.
+
+Here's a question to ask, right now lots of functions have side effects on
+globals or on function parameters via access, certainly you are not about to
+rule out
+
+    F (A'Access, A'Size)
+
+which is how I have to deal with the example above.
+
+So question? Given that this problem can arise today in what Tuck calls its
+"more dangerous" form, which cannot in any case be detected, how often have
+people actually had bugs from this kind of thing? For me it is never, which is
+why I don't think the restriction would be useful to me.
+
+I really would like to understand why Tuck would not be satisifed with the
+restriction. We have a fundamental disagreement here on the need for this rule,
+and it seems clear that the appropriate way to deal with this is to have an
+optional restriction, so that everyone can get what they want.
+
+P.S. I am also a little concerned that the language lawyering of this (to me
+useless) rule will sabotage the addition of this important feature, but
+hopefully that won't occur.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Friday, March 13, 2009  8:36 AM
+
+Maybe the restriction should be more forceful
+
+pragma Restrictions (No_In_Out_Function_Parameters);
+
+That way, people who don't like this sort of thing can get rid of it entirely.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Friday, March 13, 2009  8:43 AM
+
+> I think you have to talk about *names* not objects.  Objects are
+> run-time entities, so it is pretty hard to have compile-time rules
+> that depend on whether they overlap.
+
+such as F(A(J)) + F(A(K))
+
+where A is an array ...
+
+> I don't think the added complexity is worth it.  Assignments can still
+> be a problem in various ways.  For example, if the LHS appears as an
+> in-out parameter in a call within the RHS, it is not clear whether the
+> assignment or the copy-out would happen first:
+>
+>     X := Post_Inc(X) * 2 + X;
+>
+> What is the final value of X, presuming Post_Inc returns the original
+> value of its in-out parameter, but as a side-effect adds one to it?
+> Could the copy-out happen after the assignment to the LHS?  I'm not
+> sure.
+
+Definitely not, the copy out must occur as part of the evaluation of the
+function call, so this is quite clear semantics to me, it means
+
+either
+
+     T1 := X;                -- old X
+     T2 := Post_Inc (X) * 2; -- including modification of X
+     X := T1 + T2;
+
+or
+
+     T1 := Post_Inc (X) * 2; -- including modification of X
+     T2 := X;                -- new X
+     X := T1 + T2;
+
+if these have different effects, and one is "right", and one is "wrong", then
+this is just an example of a program incorrectly depending on order of
+evaluation. To me no big deal.
+
+> Until
+> now we haven't had to be too specific about when exactly copy-out
+> occurs (see 6.4.1(17) -- all it says is "after leaving the subprogram"
+> and allows various things to happen in an "arbitrary order").
+
+It's definitely important that the copy out is part of the
+
+> More typical is the old array copy situation:
+>
+>     A(I) := B(Post_Inc(I));
+>
+> What value of I is used to index into A?
+
+Should be the same answer as if we had written in current
+Ada:
+
+      A(I) := B(Post_Inc (I'Access));
+
+All the IN OUT is about is avoiding the junk requirement for using 'Access and
+access types, nothing more or less. In a sense it is just syntactic sugar
+(assuming that the function Post_Inc delays the updates till just before the
+return).
+
+> There is enough uncertainty that I strongly feel we should outlaw
+> having other uses of the variable in the same simple
+> statement/expression where the variable is passed as an IN-OUT
+> parameter to a function call.
+
+I see no reason for any uncertainty here
+
+P.S. of course I will prefer a (to me) broken function IN-OUT feature to none at
+all, but I always find it annoying when a language imposes what is simply a
+coding style rule based on someone's idea of what appropriate coding standards
+are, such rules are much more appropriately enforced by pragma Restrictions, or
+by external tools, which can do a much better job anyway.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Friday, March 13, 2009  8:47 AM
+
+> However, I think it would be very helpful to have some syntax to mark
+> '[in] out' parameters at the call site.  That seems more important to
+> me than forbidding the "bad" cases, but we could do both.
+
+Well ask yourself about the random number generator, do you really want to have
+some special mark, or is the interface we have now
+
+     Random (Generator)
+
+perfectly fine? This is a case where we have an IN OUT parameter in the current
+library, but we don't call it that, instead we make the implementation cheat to
+provide this capability.
+
+Actually, it is interesting to know how other implementations of Ada 95 handle
+the random case. I think I already gave the details for GNAT (we use
+Unrestricted_Access:
+
+    function Random (Gen : Generator) return Rst is
+       Genp : constant Pointer := Gen.Gen_State'Unrestricted_Access;
+
+I can't see any other acceptably efficient implementation possibility.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Friday, March 13, 2009  9:11 AM
+
+You don't need to use the GNAT-specific 'Unrestricted_Access.
+Because the object is limited, you can use a self-referencing access
+discriminant:
+
+    type Generator;
+    type Self_Ref(Gen : access Generator) is limited null record;
+
+    type Generator is limited record
+       Self : Self_Ref(Generator'Access);
+       Seed : <whatever>
+    end record;
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Friday, March 13, 2009  9:19 AM
+
+Ah yes, of course, that would be cleaner indeed! A bit less efficient, but not
+significantly so.
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Friday, March 13, 2009  9:20 AM
+
+> If you think such a restriction is useful, then add it as a
+> restriction, and those, like you, who find this restriction useful can
+> include it in your coding standard.
+
+If this feature ever sees the light, you can be sure that the corresponding rule
+will appear in AdaControl almost immediately...
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Friday, March 13, 2009  9:24 AM
+
+> I can't see any other acceptably efficient implementation possibility.
+
+The "Rosen trick" can be used for that, and I don't think the efficiency cost
+would be that big.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Friday, March 13, 2009  9:57 AM
+
+> If this feature ever sees the light, you can be sure that the
+> corresponding rule will appear in AdaControl almost immediately...
+
+Sure and that is a fine place for such a rule, where it can indeed be fine tuned
+so that there is a choice of how strenuous you want it to be. For instance a
+very cautious rule would reject:
+
+     F(A(I))+F(A(J))
+
+on the grounds that it might be a problem
+
+Of course AdaControl would also have a rule forbidding the feature entirely.
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Friday, March 13, 2009  10:13 AM
+
+> For instance a very cautious rule would reject:
+>
+>     F(A(I))+F(A(J))
+>
+> on the grounds that it might be a problem
+
+I have this one already for procedures (Parameter_Aliasing)
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Friday, March 13, 2009  10:27 AM
+
+A little bit different, since this is two separate calls!
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Friday, March 13, 2009  10:18 AM
+
+> I can't see any other acceptably efficient implementation possibility.
+
+I don't see what is wrong with making Generator an access type to the real
+generator record.  There is a little more overhead when creating a generator,
+but that should be something that doesn't happen often, usually once per
+program, so worrying about unreclaimed storage is silly.  (There will be an
+instance of the random package hanging around anyway.)
+
+In the calls to Random there should be no difference in the generated code
+between passing the generator by explicit or implicit reference.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Friday, March 13, 2009  10:29 AM
+
+> ... so worrying about unreclaimed storage is silly.
+
+Ouch!
+
+First, we have many environments in which dynamic allocation is not allowed AT
+ALL.
+
+Second, we can never not worry about a storage leak in many of our environments.
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Friday, March 13, 2009  11:39 AM
+
+First, what shouldn't get lost in this discussion is that fixing the RNG
+packages should be part of any in out function proposal.  Lots of people,
+including me, probably consider that sufficient justification for the change.
+This probably trumps the no in out function parameters at all restriction.  Or
+can it be worded to allow using functions with in out parameters declared in
+standard libraries.  I'd actually like to go through ALL the standard packages
+adding functions with in out parameters where appropriate.  (Text_IO probably
+can't be fixed, since it depends on some functions returning file objects.)  But
+a stack abstraction certainly should have a Pop function, and so on.
+
+> First, we have many environments in which dynamic allocation is not
+> allowed AT ALL.
+
+Perverse. The rule we always used was that (heap) allocators can be called
+during initialization.  Add rules about recursive calls, and known sizes for
+stack frames and you know that the application will never run out of memory.
+The no dynamic allocation rule results in much larger stack frames, and often
+makes the analysis much harder--or requires more memory.
+
+So yes, at MITRE I have been in the position of telling contractors to USE
+dynamic allocation during initialization to reduce stack frame sizes. ;-)  And
+yes, this is in avionics and radar software. ACT. of course, has to satisfy
+perverse customers. (The customer is always right, even when they are wrong.)
+
+> Second, we can never not worry about a storage leak in many of our
+> environments.
+
+The Rosen trick works, or you can just allocate a few  generators inside the RNG
+package.  What if you run out?  Start reusing them.  If a user can tell the
+difference, he has serious problems. ;-)  Or for your no heap allocation allowed
+customers (as opposed to no allocation statements) start putting generators on
+the heap after the first dozen.  Again, there are good reasons on occasion for
+having multiple generators, for example having one per task. (Very carefully
+initialized so they generate uncorrelated sequences.) But if you have too many
+generators, all of the assumptions in the RNG design break down.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Friday, March 13, 2009  11:52 AM
+
+> Perverse. The rule we always used was that (heap) allocators can be
+> called during initialization.  Add rules about recursive calls, and
+> known sizes for stack frames and you know that the application will
+> never run out of memory.  The no dynamic allocation rule results in
+> much larger stack frames, and often makes the analysis much harder--or
+> requires more memory.
+
+Not at all, yes, some DO-178B environments allow allocation at initialization
+time, but not all by any means
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Friday, March 13, 2009  11:53 AM
+
+> Perverse.
+
+Remember also that if you allow allocation during startup, it still means you
+have to certify the dynamic allocation code. Often this means that it is
+preferable to avoid DA completely. I don't know how much experience you have in
+formally certified 178B systems, but it changes a lot of thinking.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Friday, March 13, 2009  9:10 AM
+
+> > However, I think it would be very helpful to have some syntax to
+> > mark '[in] out' parameters at the call site.  That seems more
+> > important to me than forbidding the "bad" cases, but we could do both.
+>
+> Well ask yourself about the random number generator, do you really
+> want to have some special mark, or is the interface we have now
+>
+>      Random (Generator)
+>
+> perfectly fine?
+
+Well, Random takes an 'in' parameter, and I presume we're not going to change
+that, so Random(Generator) will remain correct.
+
+But if I were doing it over from scratch, then I'd make the parameter 'in out',
+and I'd like to have a restriction that forces me to mark the actual as 'in
+out'.
+
+Note that in this discussion, Randy and Tucker gave various examples, and they
+repeatedly said in English, things like "note that so-and-so is 'in out'".
+Without that explanation, I wouldn't have had the slightest idea what they were
+talking about.  This proves that it's useful information to have at call sites.
+Of course, it's not essential -- you can always go look up the declarations.
+
+>...This is a case where we have an IN OUT parameter  in the current
+>library, but we don't call it that, instead we make  the implementation
+>cheat to provide this capability.
+>
+> Actually, it is interesting to know how other implementations of Ada
+> 95 handle the random case. I think I already gave the details for GNAT
+> (we use Unrestricted_Access:
+>
+>     function Random (Gen : Generator) return Rst is
+>        Genp : constant Pointer := Gen.Gen_State'Unrestricted_Access;
+>
+> I can't see any other acceptably efficient implementation possibility.
+
+There are various ways to make self-referential pointers, so Random can just say
+something like:
+
+    Writeable_Generator : Generator renames Gen.Self.all;
+    ...
+    Writeable_Generator.Blah := ...;
+
+It's portable, and the run-time cost is pretty small.
+
+****************************************************************

Questions? Ask the ACAA Technical Agent