* AQ&S Guidance on pragma Elaborate_Body @ 1997-04-18 0:00 JP Thornley 1997-04-18 0:00 ` Robert A Duff ` (2 more replies) 0 siblings, 3 replies; 81+ messages in thread From: JP Thornley @ 1997-04-18 0:00 UTC (permalink / raw) In the rationale to Section 8.4.3, Coupling Due to Pragmas, the second paragraph says:- "When there is a clear requirement for a recursive dependency, you should use pragma Elaborate_Body. This situation arises, for example, when you have a recursive dependency (i.e., package A's body depends on package B's specification and package B's body depends on package A's specification)." The most obvious interpretation of this is that the pragma should appear in both packages - which will generate an error, probably at link/bind time. So is there a meaningful message struggling to get out here? [Perhaps "a clear requirement" can be replaced by "no requirement", so that a successful build confirms that no circular package depencies have been introduced unwittingly.] [The suspicion of poor authoring/editing is reinforced by the rather strange wording where X is an example of X.] Phil Thornley -- ------------------------------------------------------------------------ | JP Thornley EMail jpt@diphi.demon.co.uk | | phil.thornley@acm.org | ------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-18 0:00 AQ&S Guidance on pragma Elaborate_Body JP Thornley @ 1997-04-18 0:00 ` Robert A Duff 1997-04-21 0:00 ` Michael F Brenner 1997-04-18 0:00 ` Robert Dewar 1997-04-20 0:00 ` Doug Smith 2 siblings, 1 reply; 81+ messages in thread From: Robert A Duff @ 1997-04-18 0:00 UTC (permalink / raw) In article <528878564wnr@diphi.demon.co.uk>, JP Thornley <jpt@diphi.demon.co.uk> wrote: >So is there a meaningful message struggling to get out here? [Perhaps >"a clear requirement" can be replaced by "no requirement", so that a >successful build confirms that no circular package depencies have been >introduced unwittingly.] I dunno. My theory is to use the first pragma in the following list that works: Pure Preelaborate Elaborate_Body Elaborate_All Elaborate The first three make life easier, because they go on the package (rather than on all clients), and they pretty much prevent access-before-elab failures. - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-18 0:00 ` Robert A Duff @ 1997-04-21 0:00 ` Michael F Brenner 1997-04-22 0:00 ` Robert A Duff 0 siblings, 1 reply; 81+ messages in thread From: Michael F Brenner @ 1997-04-21 0:00 UTC (permalink / raw) Bob said Pure Preelaborate Elaborate_Body Elaborate_All Elaborate > The first three make life easier, because they go on the package (rather > than on all clients), and they pretty much prevent access-before-elab > failures. One more thing must be said: in reusing this software, the reuse itself might have a circular dependency, which the compiler may or may not be able to figure out. To reduce the amount of stuff that the compiler has to worry about, and to make it possible to compute a SINGLE elaboration order (without which the program may raise program_error at will), you MUST add one of the first three to all packages you think are NOT in a circular elaboration dependency loop. Doing this also helps you identify your elaboration loops more clearly, so you can deal with them using elaborate or elaborate_all or by removing the regression testing code from the elaboration-time executable statements at the bottom of the package. Failure to add these will cause needless failures when they are reused INSIDE an elaboration dependency loop. If a quality standard says they are optional, that quality standard does not reflect the reality of Ada-95 software re-use. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-21 0:00 ` Michael F Brenner @ 1997-04-22 0:00 ` Robert A Duff 0 siblings, 0 replies; 81+ messages in thread From: Robert A Duff @ 1997-04-22 0:00 UTC (permalink / raw) In article <5jfu0b$l5p@top.mitre.org>, Michael F Brenner <mfb@mbunix.mitre.org> wrote: >One more thing must be said: in reusing this software, the reuse itself >might have a circular dependency, which the compiler may or may not >be able to figure out. What do you mean by this? If by "reuse" you mean taking some existing set of packages, and using them without modification, then I don't see how you can introduce a circularity. To make a cycle, you need to add a with_clause to one of those packages. >... To reduce the amount of stuff that the compiler >has to worry about, and to make it possible to compute a SINGLE >elaboration order (without which the program may raise program_error >at will), you MUST add one of the first three to all packages you >think are NOT in a circular elaboration dependency loop. Doing this >also helps you identify your elaboration loops more clearly, so you >can deal with them using elaborate or elaborate_all or by removing >the regression testing code from the elaboration-time executable >statements at the bottom of the package. Failure to add these will >cause needless failures when they are reused INSIDE an elaboration >dependency loop. I agree that it's a good idea to put Pure, Preelaborate, or Elab_Body on everything you can, but I don't see how you can reuse something inside an elab dep loop. Unless you're changing the re-used stuff, in which case, of course, you can introduce cycles. Or plain old bugs, for that matter. Probably Elaborate_Body should have been the default (or maybe even Preelab or Pure), and there should have been a pragma to turn *off* Elab_Body, in case of mutual recursion. (By "recursion", I mean "defined in terms of itself", not necessarily recursive calling. E.g. mutually recursive type declarations can exist.) IMHO the worst thing about this stuff is that elab order is not portable. If you make a mistake, you might not find out until you're long dead and somebody else tries to port your code. - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-18 0:00 AQ&S Guidance on pragma Elaborate_Body JP Thornley 1997-04-18 0:00 ` Robert A Duff @ 1997-04-18 0:00 ` Robert Dewar 1997-04-19 0:00 ` Michael Paus 1997-04-20 0:00 ` Doug Smith 2 siblings, 1 reply; 81+ messages in thread From: Robert Dewar @ 1997-04-18 0:00 UTC (permalink / raw) JP Thornley asks <<So is there a meaningful message struggling to get out here? [Perhaps "a clear requirement" can be replaced by "no requirement", so that a successful build confirms that no circular package depencies have been introduced unwittingly.]>> I am not quite sure I can understand this, but the proper approach in Ada 95 is make packages Pure if possible else make packages Preelaborate if possible else use pragma Elaborate_Body if possible else use pragma Elaborate_All on clients if possible else take a very careful hard look at your program -- it is suspicious! ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-18 0:00 ` Robert Dewar @ 1997-04-19 0:00 ` Michael Paus 1997-04-19 0:00 ` Robert A Duff ` (2 more replies) 0 siblings, 3 replies; 81+ messages in thread From: Michael Paus @ 1997-04-19 0:00 UTC (permalink / raw) dewar@merv.cs.nyu.edu (Robert Dewar) wrote: > I am not quite sure I can understand this, but the proper approach in > Ada 95 is > > make packages Pure if possible > else > make packages Preelaborate if possible > else > use pragma Elaborate_Body if possible > else > use pragma Elaborate_All on clients if possible > else > take a very careful hard look at your program -- it is suspicious! Hm ? If there is such a simple and strict rule on how to apply this kind of pragmas, I wonder why the compiler does not do it automatically. The compiler does check whether my pragma settings are correct. So it seems to be quite straight forward for the compiler to automatically insert the highest level of purity. Are there any undesirable side effects when doing that or is the rule not as simple as you said ? Just curious Michael -- ------------------------------------------------------------------------ --Dr.-Ing. Michael Paus (Member: Team Ada) --University of Stuttgart, Inst. of Flight Mechanics and Flight Control --Forststrasse 86, 70176 Stuttgart, Germany --Phone: (+49) 711-121-1434 FAX: (+49) 711-634856 --Email: Michael.Paus@ifr.luftfahrt.uni-stuttgart.de (NeXT-Mail welcome) ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-19 0:00 ` Michael Paus @ 1997-04-19 0:00 ` Robert A Duff 1997-04-21 0:00 ` Robert Dewar 1997-04-20 0:00 ` Robert Dewar 1997-04-21 0:00 ` Michael F Brenner 2 siblings, 1 reply; 81+ messages in thread From: Robert A Duff @ 1997-04-19 0:00 UTC (permalink / raw) In article <5jabeq$3ltk@info4.rus.uni-stuttgart.de>, Michael Paus <michael@ifr.luftfahrt.uni-stuttgart.de> wrote: >Hm ? If there is such a simple and strict rule on how to apply this >kind of pragmas, I wonder why the compiler does not do it automatically. >The compiler does check whether my pragma settings are correct. So it >seems to be quite straight forward for the compiler to automatically >insert the highest level of purity. Are there any undesirable side >effects when doing that or is the rule not as simple as you said ? The compiler can't do it, because that would require knowing about a package body when compiling the package spec (or clients of the package spec). You could do it automatically at link time, but not at compile time (given Ada's compilation model). By "it", I mean "insert Pure, Preelaborate, or Elab_Body, as appropriate." Elaborate_All and Elaborate are somewhat more complicated to deal with. If you're willing to live with some restrictions, and some complicated (slow?) processing at link time, you could dispense with all elaboration-control pragmas, and have the link phase determine an elaboration order that's guaranteed to not raise Program_Error. But note that some of these pragmas (Pure, especially) have purposes other than just elaboration order. - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-19 0:00 ` Robert A Duff @ 1997-04-21 0:00 ` Robert Dewar 1997-04-23 0:00 ` Robert A Duff 0 siblings, 1 reply; 81+ messages in thread From: Robert Dewar @ 1997-04-21 0:00 UTC (permalink / raw) Robert Duff said <<If you're willing to live with some restrictions, and some complicated (slow?) processing at link time, you could dispense with all elaboration-control pragmas, and have the link phase determine an elaboration order that's guaranteed to not raise Program_Error. But note that some of these pragmas (Pure, especially) have purposes other than just elaboration order.>> No, that's quite wrong. There are many things that can place restrictions on the order of elaboration. Suppose we have a package Glorp that has several procedures including Thunk, Boggle, and Glub. In the comments of package Glorp, we find the comment: -- WARNING: It is essential to call Thunk before calling Boggle. If you -- fail to do this, all subsequent calls to Glub will raise the Glob-Glob -- exception or otherwise malfunction. Clients of Glorp are responsible for -- obeying this rule, since no check is made (a check would introduce too -- much overhead). Now, suppose we have two clients of Glorp, Jabber and Wocky. The elaboration code of Jabber calls Thunk, and the elaboration code of Wocky calls Boggle. Well now it is essential that Jabber is elaborated before Wocky, and no static analysis of the program code can determine this, and a pragma Elaborate is required. And if you think this is just theoretical, think again, there are instantiations of the names above in the SGI GNAT runtime library, and when we installed some new clever elaboration stuff (a bit like Bob proposes, but more effective, and easier to understand), the binder chose a much better elaboration order, much more clearly guaranteed to prevent Program_Error, but unfortunately wrong (of course this is a bug in the runtime, there is a missing pragma Elaborate). It is quite true that you can guarantee absence from Program_Error for a wide variety of programs automatically, and version 3.10 of GNAT does that. BUT it is far from true that this means that you could "dispense with all elaboration-control pragmas". ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-21 0:00 ` Robert Dewar @ 1997-04-23 0:00 ` Robert A Duff 1997-04-23 0:00 ` Robert Dewar 1997-04-24 0:00 ` Mats Weber 0 siblings, 2 replies; 81+ messages in thread From: Robert A Duff @ 1997-04-23 0:00 UTC (permalink / raw) In article <dewar.861642821@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: >Robert Duff said > ><<If you're willing to live with some restrictions, and some complicated >(slow?) processing at link time, you could dispense with all >elaboration-control pragmas, and have the link phase determine an >elaboration order that's guaranteed to not raise Program_Error. But >note that some of these pragmas (Pure, especially) have purposes other >than just elaboration order.>> > >No, that's quite wrong. There are many things that can place restrictions >on the order of elaboration. But my assertion was that one could be rid of Program_Errors due to calling subprograms before they've been elaborated. That's certainly true. The link-time processing would have to walk the call graph, and make sure every subprogram gets elaborated before it might be called. This is complex, and perhaps slow, and would make some (fairly obscure) legal programs illegal. I admit that your example shows a case where you want to control elaboration order, which has nothing to do with the predefined Program_Error checks. Is that something the language should help you with? I'm not sure. It seems to me that elaboration order should not be implementation dependent -- the main problem with the current Ada rules is that you can port code (or simply recompile with a new version of your compiler) and get a P_E that didn't used to happen. But your example seems questionable to me. (See below.) >Suppose we have a package Glorp that has several procedures including >Thunk, Boggle, and Glub. In the comments of package Glorp, we find the >comment: > >-- WARNING: It is essential to call Thunk before calling Boggle. If you >-- fail to do this, all subsequent calls to Glub will raise the Glob-Glob >-- exception or otherwise malfunction. Clients of Glorp are responsible for >-- obeying this rule, since no check is made (a check would introduce too >-- much overhead). OK, but tell us why Glorp doesn't simply call Thunk in its elaboration? I mean, the whole point of having elaboration is to get stuff initialized, and it should be Glorp's responsibility to do that. I will admit that no reasonable Ada implementation will understand the above comment. ;-) >Now, suppose we have two clients of Glorp, Jabber and Wocky. The elaboration >code of Jabber calls Thunk, and the elaboration code of Wocky calls Boggle. > >Well now it is essential that Jabber is elaborated before Wocky, and no >static analysis of the program code can determine this, and a pragma >Elaborate is required. > >And if you think this is just theoretical, think again, there are >instantiations of the names above in the SGI GNAT runtime library, and >when we installed some new clever elaboration stuff (a bit like Bob >proposes, but more effective, and easier to understand), the binder >chose a much better elaboration order, much more clearly guaranteed >to prevent Program_Error, but unfortunately wrong (of course this is >a bug in the runtime, there is a missing pragma Elaborate). But wouldn't the runtime be simpler if each package took care of its own initialization? >It is quite true that you can guarantee absence from Program_Error for a wide >variety of programs automatically, and version 3.10 of GNAT does that. That's all I was asserting. >...BUT >it is far from true that this means that you could "dispense with all >elaboration-control pragmas". You quote me out of context -- there's a ", and have the link phase determine an elaboration order that's guaranteed to not raise Program_Error." there. That's all I meant, although the more general situation is interesting from a language design point of view. - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-23 0:00 ` Robert A Duff @ 1997-04-23 0:00 ` Robert Dewar 1997-04-24 0:00 ` Robert A Duff 1997-04-24 0:00 ` Mats Weber 1 sibling, 1 reply; 81+ messages in thread From: Robert Dewar @ 1997-04-23 0:00 UTC (permalink / raw) Bob Duff said <<But my assertion was that one could be rid of Program_Errors due to calling subprograms before they've been elaborated.>> That was one of your assertions, and I agree with it, but you also asserted that "you could dispense with all elaboration-control pragmas", and that is more contentious, since it would reduce the expressive power of the language, no matter how clever your implementation is. You realize this of course, and then dispute my example (that's fair, if a language designer suggests removing a feature that someone thinks is essential, they can argue that it is not so essential, and that the programs affected are somehow wrong: <<OK, but tell us why Glorp doesn't simply call Thunk in its elaboration? I mean, the whole point of having elaboration is to get stuff initialized, and it should be Glorp's responsibility to do that.>> I am the client, there is no way I can change my server, especially if the server is in fact an external threads package (as was the case in the particular instance). How about Glorp is "get the next random number", and Thunk is "initialize the random number with an appropriate seed". I can quite see that the issues of initializing the random number generators for a run, and using them to compute some initial static tables might be handled in different packages. <<I admit that your example shows a case where you want to control elaboration order, which has nothing to do with the predefined Program_Error checks. Is that something the language should help you with? I'm not sure.>> If the language does not let you control elaboration order, then it should not provide elaboration, otherwise you can get into too much trouble. This can be a major problem in C++ programs, where there is no control. We have nice mechanisms in Ada that are very powerful, and allow handling cases like this nicely. I agree it would be nice if elaboration could be handled entirely statically. The problem is finding a nice model for this. Requiring a compiler to build a call graph for the entire program is painful (and indeed we explicitly rejected this possibility during the Ada 95 design effort). I think the model I have just implemented in GNAT is very attractive, it avoids the need for a program wide call graph (which would be an unattractive extra expense), but seems powerful enough in practice to handle most normal cases (we found no counter example in our regression suite, and only a couple of counter examples in the ACVC suite -- so we run the ACVC suite with the switch that requires full dynamic semantics for elaboration. However, when I implemented this, my nice circuitry for choosing a good elaboration order caused the SGI version of the runtime to blow up. The order it chose was Program_Error free, but ran afoul of some implicit ordering requirements (abstracted into my Glorp/Thunk example). Of course a pragma Elaborate or Elaborate_All properly placed would fix this. It will be interesting to see how well the GNAT static model works. Basically the short cut is to imply a pragma Elaborate)All on any package or generic that is directly or indirectly accessed in elaboration code (if it is not Pure, Preelaborate, predefined, or Elaborate_Body). For internal threads of control, the equivalent of a full call graph is used (though never explicitly built). More informatoin will be available when 3.10 and its documentation is released Robert Dewar Ada Core Technologies ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-23 0:00 ` Robert Dewar @ 1997-04-24 0:00 ` Robert A Duff 1997-04-24 0:00 ` Robert Dewar 0 siblings, 1 reply; 81+ messages in thread From: Robert A Duff @ 1997-04-24 0:00 UTC (permalink / raw) In article <dewar.861854112@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: [Elaboration-order-control features are needed.] OK, I'm convinced. I just wish that (1) I didn't have to write zillions of pragmas in the "normal" cases. E.g. maybe Elaborate_Body or Preelab should be the default, with a pragma to turn it off. And (2) that all implementations had to choose the same order for a given program. The Modula-2 rules are closer, but still don't quite make it. - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Robert A Duff @ 1997-04-24 0:00 ` Robert Dewar 1997-04-24 0:00 ` Robert Dewar ` (2 more replies) 0 siblings, 3 replies; 81+ messages in thread From: Robert Dewar @ 1997-04-24 0:00 UTC (permalink / raw) Bob said <<I just wish that (1) I didn't have to write zillions of pragmas in the "normal" cases. E.g. maybe Elaborate_Body or Preelab should be the default, with a pragma to turn it off. And (2) that all implementations had to choose the same order for a given program. The Modula-2 rules are closer, but still don't quite make it.>> In its default configuration, GNAT 3.10 does not require you to write "zillions of pragmas", and guarantees that Program_Error cannot occur. Now it is true that you can construct programs that are treated as statically illegal in this default mode, when they are in fact legal, but in practice we have found that the rules we implement (which basically assume pragma Elaborate_All if not stated where needed because of access from elaboratoin code) seem to work for a very large subset of programs. So far, we have only found a few ACVC tests that defeated these static checks. We will know more when more people have a chance to try out this new approach. Robert Dewar Ada Core Technologies. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Robert Dewar @ 1997-04-24 0:00 ` Robert Dewar 1997-04-25 0:00 ` Robert A Duff 1997-04-25 0:00 ` Mats Weber 1997-04-26 0:00 ` AQ&S Guidance on pragma Elaborate_Body Nick Roberts 2 siblings, 1 reply; 81+ messages in thread From: Robert Dewar @ 1997-04-24 0:00 UTC (permalink / raw) Following up my own message: <<In its default configuration, GNAT 3.10 does not require you to write "zillions of pragmas", and guarantees that Program_Error cannot occur. Now it is true that you can construct programs that are treated as statically illegal in this default mode, when they are in fact legal, but in practice we have found that the rules we implement (which basically assume pragma Elaborate_All if not stated where needed because of access from elaboratoin code) seem to work for a very large subset of programs.>> I should say that the one class of dynamic checks that we do not know how to eliminate results from the use of access subprograms. Obviously this is a nasty case, since it involves dynamic value tracing, which cannot be done entirely accurately, even if you attempt it. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Robert Dewar @ 1997-04-25 0:00 ` Robert A Duff 0 siblings, 0 replies; 81+ messages in thread From: Robert A Duff @ 1997-04-25 0:00 UTC (permalink / raw) In article <dewar.861936746@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: >I should say that the one class of dynamic checks that we do not know how >to eliminate results from the use of access subprograms. Obviously this >is a nasty case, since it involves dynamic value tracing, which cannot be >done entirely accurately, even if you attempt it. Presumably dispatching calls raise the same issue. - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Robert Dewar 1997-04-24 0:00 ` Robert Dewar @ 1997-04-25 0:00 ` Mats Weber 1997-04-25 0:00 ` Robert I. Eachus 1997-04-27 0:00 ` Robert Dewar 1997-04-26 0:00 ` AQ&S Guidance on pragma Elaborate_Body Nick Roberts 2 siblings, 2 replies; 81+ messages in thread From: Mats Weber @ 1997-04-25 0:00 UTC (permalink / raw) Robert Dewar wrote: > In its default configuration, GNAT 3.10 does not require you to write > "zillions of pragmas", and guarantees that Program_Error cannot occur. > Now it is true that you can construct programs that are treated as > statically illegal in this default mode, when they are in fact legal, > but in practice we have found that the rules we implement (which basically > assume pragma Elaborate_All if not stated where needed because of access > from elaboratoin code) seem to work for a very large subset of programs. ...which shows that automatic elaboration order construction is _state of the art_ (this is further confirmed by other compilers (Verdix, DEC) I use without a single pragma Elaborate* and without ever getting Program_Error). IMO, state of the art belongs in the standard, not in nice compiler specific features, which would have allowed the standard to take a different approach: automatic elaboration order consturction with pragmas to _override_ it, instead of pragmas to do the right thing in the most basic cases. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-25 0:00 ` Mats Weber @ 1997-04-25 0:00 ` Robert I. Eachus 1997-04-26 0:00 ` Nick Roberts 1997-04-27 0:00 ` Robert Dewar 1 sibling, 1 reply; 81+ messages in thread From: Robert I. Eachus @ 1997-04-25 0:00 UTC (permalink / raw) In article <336089AF.6046@elca-matrix.ch> Mats Weber <Mats.Weber@elca-matrix.ch> writes: > IMO, state of the art belongs in the standard, not in nice compiler > specific features, which would have allowed the standard to take a > different approach: automatic elaboration order consturction with > pragmas to _override_ it, instead of pragmas to do the right thing in > the most basic cases. No. State of the art should not be outlawed, and both Ada 83 and Ada 95 went along with that. But state of the art also argues for "letting a milion flowers bloom," until one prefered method emerges as "the state of the practice." There are Ada programs where not only is finding a workable elaboration order hard--in the mathematical sense--but a property of the program. Right now, the program designer has access to information not visible in the program, and based on that information there is a working elaboration order. But... Let me give you a true life example. The system archictecture has a design philosophy where each level in the architect only depends on state in a lower level. But for implementation reasons, lower level routines call upper level routines all over the place. As long as elaboration is done in the right order, from lowest level to highest, there are no ABE problems. But assigning programs to levels is not something the compiler can easily do. Sound like an extreme case? Sorry, most graphical interfaces are structured this way. Accidently, breaking those ordering rules becomes an obvious bug at run-time. In Ada, using the extra-linguistic knowledge to do elaboration means that, if it compiles, you won't have ABE problems. Since the Ada model is so much easier to life with than the model in some other languages, I'm willing to put up with the minor irritation to allow these programs to be written. (The problem when you find a circular elaboration dependency and have to fix it is not minor. But in Ada you haven't spent months tracking it down.) Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-25 0:00 ` Robert I. Eachus @ 1997-04-26 0:00 ` Nick Roberts 1997-04-26 0:00 ` Robert Dewar 0 siblings, 1 reply; 81+ messages in thread From: Nick Roberts @ 1997-04-26 0:00 UTC (permalink / raw) Perhaps it could be summarised like this: The 'call graph' (or 'call tree') of calls which occur during the elaboration of the library units of a program cannot always be statically determined. There may be (and indeed, experience suggests, there will be) situations where the potential call graph indicates a circularity (i.e. that there is no order of elaboration which the compiler can determine will ensure that an unelaborated subprogram is never called), but where there is, in fact, an elaboration order in which normal execution of the program will not cause an unelaborated subprogram to be called. This is something which only the programmer can know: it cannot be determined by the compiler. So, the programmer has got to tell the compiler the order in which to elaborate the library units (and also, perhaps, has to soothe the compiler's troubled brow, and reassure it that a call to an unelaborated subprogram will not occur ;-). Thus, elaboration pragmas are required. As for 'state of the art': ask a soldier (/airman/sailor) whether he wants weapon A, which is state-of-the-art, or weapon B, which is simple and reliable. Which do you think he will choose? Or, to put it another way, if you could buy Ada compiler product A, which is state-of-the-art (and costs $30,000), or compiler product B, which requires elaboration pragmas (and costs $3,000, and is more reliable anyway), which would you buy? Nick. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-26 0:00 ` Nick Roberts @ 1997-04-26 0:00 ` Robert Dewar 1997-04-28 0:00 ` Robert I. Eachus 0 siblings, 1 reply; 81+ messages in thread From: Robert Dewar @ 1997-04-26 0:00 UTC (permalink / raw) i<< There may be (and indeed, experience suggests, there will be) situations where the potential call graph indicates a circularity (i.e. that there is no order of elaboration which the compiler can determine will ensure that an unelaborated subprogram is never called), but where there is, in fact, an elaboration order in which normal execution of the program will not cause an unelaborated subprogram to be called.>> Well of coruse this is true, and is why a purely static solution cannot be 100% accurate. But It is *very* rare, I would say non-existent almost, for anything other than specially constructed tests to run into this, and the limitation in expressive power from forbidding such cycles is negligible. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-26 0:00 ` Robert Dewar @ 1997-04-28 0:00 ` Robert I. Eachus 1997-04-29 0:00 ` Robert Dewar 0 siblings, 1 reply; 81+ messages in thread From: Robert I. Eachus @ 1997-04-28 0:00 UTC (permalink / raw) In article <dewar.862079640@merv> dewar@merv.cs.nyu.edu (Robert Dewar) writes: > Well of coruse this is true, and is why a purely static solution > cannot be 100% accurate. But It is *very* rare, I would say > non-existent almost, for anything other than specially constructed > tests to run into this, and the limitation in expressive power > from forbidding such cycles is negligible. I thought that Robert Dewar did provide an example from GNAT where the pragmas were needed? In any case, the reality is not that there are very few programs which can be written so that the pragmas are not needed, but that the pragmas and the error messages help Ada programmers find a livable elaboration order, and to live with the situations where proper execution requires a certain elaboration order. I spent most of Friday afternoon doing just that. Now the real problem in my case was a place where the Ada rules are slightly too restrictive. (And no, I am not suggesting that they be fixed...) The problem was that I have a tagged type call it Foo, and an access type say Bar: type Foo is new Foob with private; type Bar is access all Foo'Class; So far so good, but now I want to instantiate a generic with: generic type Foobar is abstract new Foob with private; type Barf is access all Foobar; package Barfoo is ... Even though Foobar is not used within package Barfoo, I can't instantiate the generic for Foo and Bar until after the completion of the declaration Foo. (And note that abstract, it is not just that I don't declare an object of type Foobar, I can't. But there could be a (non-abstract) type derived from Foobar so it would take new syntax for something of very marginal utility. "type Foobar is abstract final new Foo with private;" for example. As I said, not worth fixing. But to get my program to compile cleanly, I had to introduce a new unit with a "programmer knowledge only" elaboration dependency. Of course I documented the reason as a comment on the pragma Elaborate_All. And, yes, I have worked with programs where the "right" elaboration order could only be determined from files read at execution time. Of course the programming team knew the right order and embedded it in Elaborates and project documentation. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-28 0:00 ` Robert I. Eachus @ 1997-04-29 0:00 ` Robert Dewar 1997-04-29 0:00 ` Robert I. Eachus 0 siblings, 1 reply; 81+ messages in thread From: Robert Dewar @ 1997-04-29 0:00 UTC (permalink / raw) Robert Eachus says << And, yes, I have worked with programs where the "right" elaboration order could only be determined from files read at execution time. Of course the programming team knew the right order and embedded it in Elaborates and project documentation.>> I find this sort of thing bad programming practice. If you are doing anything this fancy at elaboration time, it is likely to get you into trouble, and you do better to make the "elaboration" explicit rather than implicit, by introducing appropriate explicit initialization routines. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-29 0:00 ` Robert Dewar @ 1997-04-29 0:00 ` Robert I. Eachus 0 siblings, 0 replies; 81+ messages in thread From: Robert I. Eachus @ 1997-04-29 0:00 UTC (permalink / raw) I said: > And, yes, I have worked with programs where the "right" > elaboration order could only be determined from files read at > execution time. Of course the programming team knew the right order > and embedded it in Elaborates and project documentation. In article <dewar.862311716@merv> dewar@merv.cs.nyu.edu (Robert Dewar) writes: > I find this sort of thing bad programming practice. If you are > doing anything this fancy at elaboration time, it is likely to > get you into trouble, and you do better to make the "elaboration" > explicit rather than implicit, by introducing appropriate > explicit initialization routines. Unfortunately, in Ada 95 it is becoming more common, not because programmers want to, but because of the rules surrounding tagged types. If you need to have a tagged type declaration depend on read in from a file, especially for a controlled type, you have to open and read the file before the start of the main program. If you want to keep all the configuration information in a single file, you then have to control the order of elaboration. I don't find this particularly distressing. But it is makework in the sense that you should write "outer" exception handlers around every package body sequence of statements, instead of once for the main program. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-25 0:00 ` Mats Weber 1997-04-25 0:00 ` Robert I. Eachus @ 1997-04-27 0:00 ` Robert Dewar 1997-04-28 0:00 ` Mats Weber 1997-04-29 0:00 ` Redefinition of "=", elaboration and learning Ada Mats Weber 1 sibling, 2 replies; 81+ messages in thread From: Robert Dewar @ 1997-04-27 0:00 UTC (permalink / raw) Mats says <<...which shows that automatic elaboration order construction is _state of the art_ (this is further confirmed by other compilers (Verdix, DEC) I use without a single pragma Elaborate* and without ever getting Program_Error). IMO, state of the art belongs in the standard, not in nice compiler specific features, which would have allowed the standard to take a different approach: automatic elaboration order consturction with pragmas to _override_ it, instead of pragmas to do the right thing in the most basic cases.>> Please don't generalize from your experience -- this could just mean that you use elaboration very lightly. Others use it more heavily, and pragma Elaborate can be critical -- here is an extreme, though real, example. There is one Ada 83 compiler, written in Ada 83, where the main program is null, and all the compiler passes are in elaboration code. Pragma Elaborate is critical for ensuring that the passes of the compiler run in the right order. Sure, for the simple case you have DEC and Verdix (and most likely GNAT as well) run fine, but I can *guarantee* that they are not consistent in the set of programs that they can successfully handle statically. We cannot have a statement in the standard that says "Elaboration shall be automatically handled sufficiently well so that Mats Weber's programs run without Program_Error", what we need is a very precise charaterization of the set of programs that are to be considered legal. Mats, what is this subset that you propose? in detail? ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-27 0:00 ` Robert Dewar @ 1997-04-28 0:00 ` Mats Weber 1997-04-29 0:00 ` Redefinition of "=", elaboration and learning Ada Mats Weber 1 sibling, 0 replies; 81+ messages in thread From: Mats Weber @ 1997-04-28 0:00 UTC (permalink / raw) Robert Dewar wrote: > We cannot have a statement in the standard that says "Elaboration shall be > automatically handled sufficiently well so that Mats Weber's programs run > without Program_Error", what we need is a very precise charaterization of > the set of programs that are to be considered legal. > > Mats, what is this subset that you propose? in detail? It's at <http://lglwww.epfl.ch/Team/MW/Ada-Extensions/Ada-Extensions.html>, sections 2.7 and 4.5 (scroll down a little for the table of contents). ^ permalink raw reply [flat|nested] 81+ messages in thread
* Redefinition of "=", elaboration and learning Ada 1997-04-27 0:00 ` Robert Dewar 1997-04-28 0:00 ` Mats Weber @ 1997-04-29 0:00 ` Mats Weber 1997-04-29 0:00 ` Robert A Duff 1 sibling, 1 reply; 81+ messages in thread From: Mats Weber @ 1997-04-29 0:00 UTC (permalink / raw) Another reason why I think we should have automatic elaboration order calculation that works in the simple cases, and no reemergence of predefined operations once they have been redefined, is that the majority of Ada programmers do not understand these problems because they have never studied the language to that level of detail (which is perfectly OK, one should not be required to read the entire RM three times to be able to write a piece of software in Ada). Having to use pragma Elaborate_All when instantiating a generic at the libarary level is, IMO, counterintuitive and unnecessarilly complicated. Having predefined "=" reemerge in strange places when it's been redefined is also counterintuitive, and the text in chapter 12 of the RM won't help you much if you are not a language lawyer or compiler writer. And then try explaining to a novice programmer, without making him believe that the language definition is flawed, that if he makes his type tagged then everything will work fine :-) What the user sees when he discovers packages and private types is that he can define abstractions that he can use without knowing how they are implemented. What he sees when he discovers a library of generic components is that he can instantiate them and then use them. In both cases, he hits what is IMO a severe pitfall: reemergence breaks his abstraction, and he (potentially) gets Program_Error when he instantiates his generic. For me, these are not really severe problems (except that I don't like the way they were handled in Ada 95) because I know how to fix them. But how is a beginner going to find his way to tagged types or elaboration pragmas ? Not very easily I think, unless he reads comp.lang.ada :-) ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: Redefinition of "=", elaboration and learning Ada 1997-04-29 0:00 ` Redefinition of "=", elaboration and learning Ada Mats Weber @ 1997-04-29 0:00 ` Robert A Duff 1997-04-30 0:00 ` Mats Weber 0 siblings, 1 reply; 81+ messages in thread From: Robert A Duff @ 1997-04-29 0:00 UTC (permalink / raw) In article <3365E879.567F@elca-matrix.ch>, Mats Weber <Mats.Weber@elca-matrix.ch> wrote: >Another reason why I think we should have... no reemergence of >predefined operations ... >Having predefined "=" reemerge in strange places when it's been >redefined is also counterintuitive ... You talk about "=" specifically, but above you say "operators", presumably meaning all of them. You still haven't given a complete definition of when *all* operators should and should not "reemerge". >And then try explaining to a novice programmer, without making him >believe that the language definition is flawed, that if he makes his >type tagged then everything will work fine :-) OK, but try to explain to the novice why Text_IO.Integer_IO doesn't work, because "mod" is redefined. >What the user sees when he discovers packages and private types is that >he can define abstractions that he can use without knowing how they are >implemented. What he sees when he discovers a library of generic >components is that he can instantiate them and then use them. In both >cases, he hits what is IMO a severe pitfall: reemergence breaks his >abstraction, and he (potentially) gets Program_Error when he >instantiates his generic. But having the user-defined operator used in a generic has a similar problem. How can I write Text_IO.Integer_IO (or a similar generic)? How do I write the code that converts an integer to a string, if I can't get my hands on the predefined ops? I agree with you about elaboration -- the current rules are a mess. And I mostly agree with you about "=". But I don't see how you can sensibly extend it to other ops. Perhaps one wants to have *both* available -- Eiffel is sort of like that. You define something like Basic_Compare and Compare, and then never override Basic_Compare (freeze it). So then a client can choose one or the other. By default, they do the same thing, but subclasses can override Compare. - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: Redefinition of "=", elaboration and learning Ada 1997-04-29 0:00 ` Robert A Duff @ 1997-04-30 0:00 ` Mats Weber 0 siblings, 0 replies; 81+ messages in thread From: Mats Weber @ 1997-04-30 0:00 UTC (permalink / raw) Robert A Duff wrote: > > In article <3365E879.567F@elca-matrix.ch>, > Mats Weber <Mats.Weber@elca-matrix.ch> wrote: > >Another reason why I think we should have... no reemergence of > >predefined operations ... > > >Having predefined "=" reemerge in strange places when it's been > >redefined is also counterintuitive ... > > You talk about "=" specifically, but above you say "operators", > presumably meaning all of them. You still haven't given a complete > definition of when *all* operators should and should not "reemerge". Yes, I want the same treatment for all operators. I was just using equality as an example because it is so important. A fairly complete statement of what I would like (or would have liked) is in my thesis at <http://lglwww.epfl.ch/Team/MW/Ada-Extensions/Ada-Extensions.html#RTFToC95> I had overlooked the case statments at the time, but the general idea is still valid. > >And then try explaining to a novice programmer, without making him > >believe that the language definition is flawed, that if he makes his > >type tagged then everything will work fine :-) > > OK, but try to explain to the novice why Text_IO.Integer_IO doesn't > work, because "mod" is redefined. I find that more natural (just my opinion): if you change the arithmetic of a type, packages that use the arithmetic are naturally affected. And Text_IO.Integer_IO could very well internally convert to another type in order to get the normal arithmetic operations, if that is really required. Anyway, there are other similar situations in Ada 83: type Tiny is range 1 .. 3; generic type T is range <>; pakcage P is ... if P uses the literal 10 in its body, it will fail when instantiated with T => Tiny (and Ada 83 had no 'Base attribute to solve this). > >What the user sees when he discovers packages and private types is that > >he can define abstractions that he can use without knowing how they are > >implemented. What he sees when he discovers a library of generic > >components is that he can instantiate them and then use them. In both > >cases, he hits what is IMO a severe pitfall: reemergence breaks his > >abstraction, and he (potentially) gets Program_Error when he > >instantiates his generic. > > But having the user-defined operator used in a generic has a similar > problem. How can I write Text_IO.Integer_IO (or a similar generic)? > How do I write the code that converts an integer to a string, if I can't > get my hands on the predefined ops? You can always get your hands on the predefined ops by declaring a new type with the same (or maximal) range and type conversions. Text_IO.Integer_IO had to do this anyway because of subtype problems (excluding 0 for instance) and the lack of a usable 'base attribute in Ada 83. So it is even likely that the existing Ada 83 implementations of Text_IO.Integer_IO would work even if reemergence of predefined operations was totally removed. > I agree with you about elaboration -- the current rules are a mess. > And I mostly agree with you about "=". But I don't see how you can > sensibly extend it to other ops. Perhaps one wants to have *both* What do you mean by "other ops" ? Things like case, or things like "+", "*". For "+", "*", I would definitely take the same approach as for "=". > available -- Eiffel is sort of like that. You define something like > Basic_Compare and Compare, and then never override Basic_Compare (freeze > it). So then a client can choose one or the other. By default, they do > the same thing, but subclasses can override Compare. You can also get the predefined operations in Ada, see above. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Robert Dewar 1997-04-24 0:00 ` Robert Dewar 1997-04-25 0:00 ` Mats Weber @ 1997-04-26 0:00 ` Nick Roberts 1997-04-26 0:00 ` Robert Dewar 2 siblings, 1 reply; 81+ messages in thread From: Nick Roberts @ 1997-04-26 0:00 UTC (permalink / raw) Robert Dewar <dewar@merv.cs.nyu.edu> wrote in article <dewar.861936524@merv>... > > In its default configuration, GNAT 3.10 does not require you to write > "zillions of pragmas", and guarantees that Program_Error cannot occur. > Now it is true that you can construct programs that are treated as > statically illegal in this default mode, when they are in fact legal, > but in practice we have found that the rules we implement (which basically > assume pragma Elaborate_All if not stated where needed because of access > from elaboratoin code) seem to work for a very large subset of programs. > > So far, we have only found a few ACVC tests that defeated these static > checks. We will know more when more people have a chance to try out this > new approach. > > Robert Dewar > Ada Core Technologies. This is very neat, but wouldn't it be better, for cases where it is not strictly determinate, simply for the compiler to issue a warning that Program_Error may be (or 'is likely to be') raised, and compile as normal? Surely this would give the best of both worlds. Nick. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-26 0:00 ` AQ&S Guidance on pragma Elaborate_Body Nick Roberts @ 1997-04-26 0:00 ` Robert Dewar 0 siblings, 0 replies; 81+ messages in thread From: Robert Dewar @ 1997-04-26 0:00 UTC (permalink / raw) <<This is very neat, but wouldn't it be better, for cases where it is not strictly determinate, simply for the compiler to issue a warning that Program_Error may be (or 'is likely to be') raised, and compile as normal? Surely this would give the best of both worlds.>> We can operate in this model with no problem with the appropriate switches, but I don't think this is an appropriate default. We have found tha the huge majority of existing Ada code is full of instances which would generate such warnings -- i.e. a LOT of code is relying on a friendly linker, and people are not necessarily intersted in doing a lot of work on their code to avoid this .. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-23 0:00 ` Robert A Duff 1997-04-23 0:00 ` Robert Dewar @ 1997-04-24 0:00 ` Mats Weber 1997-04-24 0:00 ` Robert A Duff 1997-04-25 0:00 ` Robert Dewar 1 sibling, 2 replies; 81+ messages in thread From: Mats Weber @ 1997-04-24 0:00 UTC (permalink / raw) Robert A Duff wrote: > It seems to me that elaboration order should not be implementation > dependent -- the main problem with the current Ada rules is that you can > port code (or simply recompile with a new version of your compiler) and > get a P_E that didn't used to happen. I agree 100% here, and the solution was described at least in two articles before or during the Ada 9X effort. I still don't understand why it's not in the language. Moreover, most compilers I have used do a very good job of putting packages in a 'good' elaboration order, to the point that I almost never bother using the elaboration pragmas, taking the risk of hitting a bad compiler some time in the future (which won't be GNAT, given the effort being made to solve the problem :-). I really think this elaboration stuff should fixed in an AI (of course only the part that ensures Program_Error is not raised on a subprogram call or generic instantiation). Do you think that would be possible, or will we have to wait until Ada 0X ? :-) ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Mats Weber @ 1997-04-24 0:00 ` Robert A Duff 1997-04-24 0:00 ` Robert Dewar 1997-04-25 0:00 ` Robert Dewar 1 sibling, 1 reply; 81+ messages in thread From: Robert A Duff @ 1997-04-24 0:00 UTC (permalink / raw) In article <335F5449.6644@elca-matrix.ch>, Mats Weber <Mats.Weber@elca-matrix.ch> wrote: >I really think this elaboration stuff should fixed in an AI (of course >only the part that ensures Program_Error is not raised on a subprogram >call or generic instantiation). Do you think that would be possible, or >will we have to wait until Ada 0X ? :-) Well, the ARG is normally a bit more conservative than that, but you can submit a comment if you like, and it will get turned into an AI. Of course, the AI might say, "Tough luck, elaboration stuff is a pain in the neck, and that's that." - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Robert A Duff @ 1997-04-24 0:00 ` Robert Dewar 0 siblings, 0 replies; 81+ messages in thread From: Robert Dewar @ 1997-04-24 0:00 UTC (permalink / raw) <<>I really think this elaboration stuff should fixed in an AI (of course >only the part that ensures Program_Error is not raised on a subprogram >call or generic instantiation). Do you think that would be possible, or >will we have to wait until Ada 0X ? :-)>> This would introduce serious incompatibilities in legacy code. There is nothing to stop indvidual compilers from impleemenjting some static scheme, but it cannot be mandated. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Mats Weber 1997-04-24 0:00 ` Robert A Duff @ 1997-04-25 0:00 ` Robert Dewar 1 sibling, 0 replies; 81+ messages in thread From: Robert Dewar @ 1997-04-25 0:00 UTC (permalink / raw) <<I agree 100% here, and the solution was described at least in two articles before or during the Ada 9X effort. I still don't understand why it's not in the language.>> The "solution" which for example is described in published papers from the Binghamton group (I believe they published at Tri-Ada, as well as an article in CACM), is indeed attractive, but there are two problems: 1. We have to decide how far to make a compiler go. Requiring the construction of a call graph covering the whole program is very expensive. 2. We have to worry about backwards compatibility. I actually pushed quite strongly during the Ada 9X process to try to solve this problem, but we just did not find a satisfactory solution. No one liked solutions that would require the construction of a full call graph. I don't know if Mats solution has this quality, but certainly the Binghamton papers expect this. Obviously you cannot completely solve the compatibility problem with any static approach, since it is trivial to show that soving the elaboration problem in full gnerality is equivalent to the halting problem (folks at Softech showed this early on, this discussion is not new, it was on the table during the Ada 83 design, and the static solutions involving call graph construction were well known at that time -- of course the engineering details in such schemes are always tricky!) If you build a full call graph, you can solve most practical problems (although there exist at least some test programs around which will defeat any static scheme). The question is whether there are schemes that are good enough, and compatible enough. I am hoping the GNAT scheme will turn out to be such a scheme. Basically in GNAT we do a full call graph analysis within units, but for references across unit boundaries, we assume pragma Elaborate_All in the default mode -- this seems to work pretty well in practice, though one can certainly concoct examples that will defeat it. (We have switches to revert to the fully dynamic view i that is what you want). The nastiest problem is with access typs (generic formal subprograms would cause the same problem if you had shared generics, but not with macro generics). The trouble is that if you compute X'Access at a point before the boxy of X is elaborated -- that is perfectly reasonable, and not in any sense an error, or even in any sense poor practice (consider the implicit case with tagged type dispatching tables for example). But if X is in a separate unit that is not Pure or Preelaborate or Elaborate_Body or predefned, you cannot avoiud a dynamic check. The GNAT approach in this situation is: (a) generate a warning (if you enable these special elaboration warnings) that this is happening. (b) generate a wrapper that does the dynamic check, and point to the wrapper (c) where possible (and in particular for dispatching tables), recompute all access types as soon as elaboration is complete to eliminate the wrapper overhead. Note that another goal of the GNAT approach is to provide a set of warnings that have the quality that if you eliminate all warnings, then not only is your program guaranteed not to raise Program_Error on any implementation, but also, at least in GANT, you are guaranteed that no dynamic checks will have been generated. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-19 0:00 ` Michael Paus 1997-04-19 0:00 ` Robert A Duff @ 1997-04-20 0:00 ` Robert Dewar 1997-04-21 0:00 ` Michael F Brenner 2 siblings, 0 replies; 81+ messages in thread From: Robert Dewar @ 1997-04-20 0:00 UTC (permalink / raw) Michael Paus said <<Hm ? If there is such a simple and strict rule on how to apply this kind of pragmas, I wonder why the compiler does not do it automatically. The compiler does check whether my pragma settings are correct. So it seems to be quite straight forward for the compiler to automatically insert the highest level of purity. Are there any undesirable side effects when doing that or is the rule not as simple as you said ? Just curious Michael>> Think carefuly here -- pragmas Pure and Preelaborate are applied to specs, and determine legality of clients, but the conditoins that need checkiong apply to bodies. Unless you want to create very peculiar dependenceis (basically a horrible dependence on all possible bodies), you do ONT NOT want the compiler to do this automatically. Furthermore, the viaiblity of Elaborate_Body cannot be checked till link time. That being said, the compiler can do FAR more to help here, and the latest version of GNAT has some extremely useful additions in this area, to be announced in detail later. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-19 0:00 ` Michael Paus 1997-04-19 0:00 ` Robert A Duff 1997-04-20 0:00 ` Robert Dewar @ 1997-04-21 0:00 ` Michael F Brenner 1997-04-23 0:00 ` Robert Dewar 2 siblings, 1 reply; 81+ messages in thread From: Michael F Brenner @ 1997-04-21 0:00 UTC (permalink / raw) Michael Paus asks > ... seems to be quite straight forward for the compiler to automatically > ... insert the highest level of purity. Are there any undesirable side > ... effects when doing that or is the rule not as simple as you said ? You cannot modify the body of a PURE package to add in, for example, text_io, or any other non-pure package for debugging purposes at a later time, without busting the purity of everything that withs the PURE package. You also may not reuse a pure generic package in a way that introduces any memory, because of the rule that the compiler may optimize away repeated calls with the same arguments. Gnat in its current state (3.07 DOS) optimizes pure packages that implement limited private data structures better than impure packages. ROMable code should be PURE. There text_io comment applies to preelaborate, since some debugging packages you may wish to introduce will be non-preelaborable. Reentrant code should be preelaborable, but the data section will not be PURE. There are no disadvantages to marking elaborable packages as ELABORATE_BODY, and they should be so marked for both documentation and for compiler hinting. The goal should be that almost all of the non-thread-safe code should be marked ELABORATE_BODY, and almost all of the thread-safe code should be marked PREELABORATE or PURE. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-21 0:00 ` Michael F Brenner @ 1997-04-23 0:00 ` Robert Dewar 1997-04-24 0:00 ` Laurent Guerby 1997-04-24 0:00 ` Matthew Heaney 0 siblings, 2 replies; 81+ messages in thread From: Robert Dewar @ 1997-04-23 0:00 UTC (permalink / raw) Michael says <<You cannot modify the body of a PURE package to add in, for example, text_io, or any other non-pure package for debugging purposes at a later time, without busting the purity of everything that withs the PURE package. You also may not reuse a pure generic package in a way that introduces any memory, because of the rule that the compiler may optimize away repeated calls with the same arguments. Gnat in its current state (3.07 DOS) optimizes pure packages that implement limited private data structures better than impure packages. ROMable code should be PURE. >> I often find it quite annoying not being able to use Text_IO for debugging purposes in a pure or preelaborable package. There are two ways around it. One is to use GNAT.IO, which is at least preelaborable (maybe we should cheat and call it pure, but it really isn't). The other is to use the secret switch -gnatdu: -- du Uncheck categorization pragmas. This debug switch causes the -- categorization pragmas (Pure, Preelaborate etc) to be ignored -- so that normal checks are not made (this is particularly useful -- for adding temporary debugging code to units that have pragmas -- that are inconsistent with the debugging code added. well it is not *that* secret. it is one of the GNAT debugging switches that are documented in debug.adb :-) <<There are no disadvantages to marking elaborable packages as ELABORATE_BODY, and they should be so marked for both documentation and for compiler hinting. >> That is incorrect, you can certainly create cases of legitimate programs where the use of Elaborate_Body will cause elaboration circularities. A trivial example is two packages, each of whose bodies with's the others spec, which is not that uncommon. <<The goal should be that almost all of the non-thread-safe code should be marked ELABORATE_BODY, and almost all of the thread-safe code should be marked PREELABORATE or PURE.>> I have no idea what Michael has in mind here. This has nothing at all to do with thread safety. Elaboration and thread safety are entirely unrelated issues. In particular, a common idiom is to complete the elaboration before any tasks are started up. Robert Dewar Ada Core Technologies ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-23 0:00 ` Robert Dewar @ 1997-04-24 0:00 ` Laurent Guerby 1997-04-24 0:00 ` Matthew Heaney 1 sibling, 0 replies; 81+ messages in thread From: Laurent Guerby @ 1997-04-24 0:00 UTC (permalink / raw) dewar@merv.cs.nyu.edu (Robert Dewar) writes: > I often find it quite annoying not being able to use Text_IO for debugging > purposes in a pure or preelaborable package. There are two ways around it. > One is to use GNAT.IO, which is at least preelaborable (maybe we should > cheat and call it pure, but it really isn't). > > The other is to use the secret switch -gnatdu: I posted a while ago another "Pure" Ada solution: use the pragma Import from a Pure package is not disallowed, so you can import your favorite Put_Line routine (it made Bob duff happy is I remember well ;-). Shouldn't this be in the programming FAQ? -- Laurent Guerby <guerby@gnat.com>, Team Ada. "Use the Source, Luke. The Source will be with you, always (GPL)." ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-23 0:00 ` Robert Dewar 1997-04-24 0:00 ` Laurent Guerby @ 1997-04-24 0:00 ` Matthew Heaney 1997-04-24 0:00 ` Robert Dewar ` (3 more replies) 1 sibling, 4 replies; 81+ messages in thread From: Matthew Heaney @ 1997-04-24 0:00 UTC (permalink / raw) In article <dewar.861816859@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote: >That is incorrect, you can certainly create cases of legitimate programs >where the use of Elaborate_Body will cause elaboration circularities. A >trivial example is two packages, each of whose bodies with's the others >spec, which is not that uncommon. It may be true that it "is not that uncommon," but mutual dependency of packages indicates that you have a pair of highly cohesive abstractions, and they should really be combined into a single package. -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Matthew Heaney @ 1997-04-24 0:00 ` Robert Dewar 1997-04-24 0:00 ` Jon S Anthony ` (2 subsequent siblings) 3 siblings, 0 replies; 81+ messages in thread From: Robert Dewar @ 1997-04-24 0:00 UTC (permalink / raw) Matthew Heaney says <<It may be true that it "is not that uncommon," but mutual dependency of packages indicates that you have a pair of highly cohesive abstractions, and they should really be combined into a single package.>> I strongly disagree. This is a recipe for giant packages for no good reason. For example, it is perfectly reasonable to have a list package that allows lists of sets (within the sets package), where the sets package is implementd in terms of lists -- there are many such examples. Sure, if there is mutual recursion at the spec level, then you combine the packages, indeed Ada insists on it, although many feel that one of thje big weaknesses in Ada 95 is that it does not allow mutually recursive package specs. But at the body level there is absolutlely not reason to take this position. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Matthew Heaney 1997-04-24 0:00 ` Robert Dewar @ 1997-04-24 0:00 ` Jon S Anthony 1997-04-24 0:00 ` Matthew Heaney 1997-04-25 0:00 ` Robert Dewar 1997-04-24 0:00 ` Robert A Duff 1997-04-25 0:00 ` Michael F Brenner 3 siblings, 2 replies; 81+ messages in thread From: Jon S Anthony @ 1997-04-24 0:00 UTC (permalink / raw) In article <mheaney-ya023680002404970907100001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes: > >That is incorrect, you can certainly create cases of legitimate programs > >where the use of Elaborate_Body will cause elaboration circularities. A > >trivial example is two packages, each of whose bodies with's the others > >spec, which is not that uncommon. > > It may be true that it "is not that uncommon," but mutual dependency of > packages indicates that you have a pair of highly cohesive abstractions, > and they should really be combined into a single package. Hmmm, you're probably about the only one left here that believes this. The "withing problem" (and this is for SPECS, not just the above sort of case) has been discussed here extensively and the general consensus is that this inability (to define mutually dependent types across package boundaries) is a hole in the language. The great maker himself, STT, has come to hold this position. BTW, anyone know whatever became of Tucker's proposal of "with package.type" for solving this?? I know it wasn't going to be "formally" accepted somehow, but wasn't there going to be some sort of general agreement to provide this? /Jon -- Jon Anthony Organon Motives, Inc. Belmont, MA 02178 617.484.3383 jsa@organon.com ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Jon S Anthony @ 1997-04-24 0:00 ` Matthew Heaney 1997-04-26 0:00 ` Nick Roberts 1997-04-26 0:00 ` Robert Dewar 1997-04-25 0:00 ` Robert Dewar 1 sibling, 2 replies; 81+ messages in thread From: Matthew Heaney @ 1997-04-24 0:00 UTC (permalink / raw) In article <JSA.97Apr24162056@alexandria>, jsa@alexandria (Jon S Anthony) wrote: >>>A trivial example is two packages, each of whose bodies with's the others >> >spec, which is not that uncommon. >> >> It may be true that it "is not that uncommon," but mutual dependency of >> packages indicates that you have a pair of highly cohesive abstractions, >> and they should really be combined into a single package. > >Hmmm, you're probably about the only one left here that believes this. >The "withing problem" (and this is for SPECS, not just the above sort >of case) has been discussed here extensively and the general consensus >is that this inability (to define mutually dependent types across >package boundaries) is a hole in the language. You're right, I'm not especially passionate about wanting to define mutually recursive types across package boundaries. I think it's a cool idea, though. One of the tricks C++ programmers do is to pass a reference to an object as a method parameter. That way, you don't have to #include the other class because you know an address is going to get passed. Knowing that tagged types are passed by reference, perhaps we could avoid a spec dependency on the package containing a tagged type's declaration: with Q.T is tagged limited private; package P is type S is private; procedure Op (OS : in out S; OT : in Q.T); -- OT is passed by reference ... In this example, spec deferral makes sense. Sometimes, though, you have closely-related abstractions - maybe the dependency is in one direction only, or maybe they're "merely" logically cohesive - and they just sort of belong together. Of course, avoiding unnecessary compilation dependencies is A Very Good Thing, especially in Ada, where value semantics is the norm, and heap allocation is to be avoided. So there is a very real tension between the need to minimize compilation dependencies, and the desire to minimize the "declaration span" between closely-related types. Yes, we have to program real systems on real computers, but it's still humans that have to do it. -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Matthew Heaney @ 1997-04-26 0:00 ` Nick Roberts 1997-04-26 0:00 ` Robert A Duff 1997-04-26 0:00 ` Matthew Heaney 1997-04-26 0:00 ` Robert Dewar 1 sibling, 2 replies; 81+ messages in thread From: Nick Roberts @ 1997-04-26 0:00 UTC (permalink / raw) Matthew Heaney <mheaney@ni.net> wrote in article <mheaney-ya023680002404972329250001@news.ni.net>... > Knowing that tagged types are passed by reference, perhaps we could avoid a > spec dependency on the package containing a tagged type's declaration: > > with Q.T is tagged limited private; > package P is > > type S is private; > > procedure Op (OS : in out S; OT : in Q.T); -- OT is passed by reference > ... It's a nice idea. The problem with this idea, though (I think), is that there are no operations defined for Q.T for use in the body of procedure Op. What is Op able to do with the parameter OT? Anything? Nick. PS: If we had with Q.T is abstract tagged limited private; we could then derive from Q.T, add our own operations, and then use those operations (only). But would this ever be useful? ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-26 0:00 ` Nick Roberts @ 1997-04-26 0:00 ` Robert A Duff 1997-04-26 0:00 ` Matthew Heaney 1 sibling, 0 replies; 81+ messages in thread From: Robert A Duff @ 1997-04-26 0:00 UTC (permalink / raw) In article <01bc5250$db1b6c00$28f982c1@xhv46.dial.pipex.com>, Nick Roberts <Nick.Roberts@dial.pipex.com> wrote: >It's a nice idea. The problem with this idea, though (I think), is that >there are no operations defined for Q.T for use in the body of procedure >Op. What is Op able to do with the parameter OT? Anything? Various ideas along these lines were discussed here a year or two ago. Basically, the idea would be that the spec can't do much of anything with the imported type -- it's more-or-less like an incomplete type. Declare access-to-OT'Class parameters, and perhaps not much more. The body would then do a normal with_clause, and could therefore see all the operations of OT. - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-26 0:00 ` Nick Roberts 1997-04-26 0:00 ` Robert A Duff @ 1997-04-26 0:00 ` Matthew Heaney 1 sibling, 0 replies; 81+ messages in thread From: Matthew Heaney @ 1997-04-26 0:00 UTC (permalink / raw) In article <01bc5250$db1b6c00$28f982c1@xhv46.dial.pipex.com>, "Nick Roberts" <Nick.Roberts@dial.pipex.com> wrote: >> Knowing that tagged types are passed by reference, perhaps we could avoid >a >> spec dependency on the package containing a tagged type's declaration: >> >> with Q.T is tagged limited private; >> package P is >> >> type S is private; >> >> procedure Op (OS : in out S; OT : in Q.T); -- OT is passed by >reference >> ... > > >It's a nice idea. The problem with this idea, though (I think), is that >there are no operations defined for Q.T for use in the body of procedure >Op. What is Op able to do with the parameter OT? Anything? I said "avoid a __spec__ dependency." Of course, a with of package Q by the body of P is required. We're trying to make specs less sensitive to changes in the packages is withs, to reduce the ripple-effect in a large system (because the library units that with P would have to be (potentially) checked, and so on). -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Matthew Heaney 1997-04-26 0:00 ` Nick Roberts @ 1997-04-26 0:00 ` Robert Dewar 1997-04-26 0:00 ` Matthew Heaney 1 sibling, 1 reply; 81+ messages in thread From: Robert Dewar @ 1997-04-26 0:00 UTC (permalink / raw) Matthew Heaney said <<You're right, I'm not especially passionate about wanting to define mutually recursive types across package boundaries.>> That's fair enough, but what puzzled everyone was that you *do* seem passionate about not wanting even mutual body dependencies (i.e. situations where the bodies of two packages A, and B, both with one another's specs) Are you really *sure* you meant to say this -- it is a rather extraordinary position, and I must say I have not seen any large scale Ada program that did not have such dependencies, they seem routine to me! ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-26 0:00 ` Robert Dewar @ 1997-04-26 0:00 ` Matthew Heaney 1997-04-27 0:00 ` Robert Dewar 0 siblings, 1 reply; 81+ messages in thread From: Matthew Heaney @ 1997-04-26 0:00 UTC (permalink / raw) In article <dewar.862097521@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote: ><<You're right, I'm not especially passionate about wanting to define >mutually recursive types across package boundaries.>> > >That's fair enough, but what puzzled everyone was that you *do* seem >passionate about not wanting even mutual body dependencies (i.e. situations >where the bodies of two packages A, and B, both with one another's specs) > >Are you really *sure* you meant to say this -- it is a rather extraordinary >position, and I must say I have not seen any large scale Ada program that >did not have such dependencies, they seem routine to me! Perhaps our experience is different. I have seen relatively few instances of such a relationship (nor have I myself had much reason to do write anything like that). But when I have seen them, they were completely unnecessary (confusing, in fact), and clearly indicated that the abstractions needed to be combined into a single package. I'm talking about just a pair of abstract data types that are intimately related. But I sense that you and the other posters are talking about large packages (say, a subprogram library such as binding). -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-26 0:00 ` Matthew Heaney @ 1997-04-27 0:00 ` Robert Dewar 1997-04-29 0:00 ` John G. Volan 0 siblings, 1 reply; 81+ messages in thread From: Robert Dewar @ 1997-04-27 0:00 UTC (permalink / raw) Matthew Heaney says <<I'm talking about just a pair of abstract data types that are intimately related. But I sense that you and the other posters are talking about large packages (say, a subprogram library such as binding).>> Not necessarily, you can find lots of examples -- I am still surprised if you really never ran across this in your own code. I have not seen any large (say a couple of hundred thousand lines up) Ada program that did NOT have this kind of mutual dependencies -- it is really a natural consequence of any domain in which recursion is an important idiom. For example, if we have a compiler with separate units to handle if statements and loop statements, it is natural for if's to have loops and loops to have if's. Surely you don't think this means that we have to put loops and if's in the same unit -- because if you do you are syaing the whole compiler must be one unit! Another example is that Text_IO might well with some FPT conversion unit, that might well have debugging statements that under a switch call Put_Line in Text_IO. and on and on and on ... ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-27 0:00 ` Robert Dewar @ 1997-04-29 0:00 ` John G. Volan 1997-04-29 0:00 ` Matthew Heaney 0 siblings, 1 reply; 81+ messages in thread From: John G. Volan @ 1997-04-29 0:00 UTC (permalink / raw) Matthew Heaney wrote: > I'm talking about just a pair of abstract data types that are intimately > related. But I sense that you and the other posters are talking about > large packages (say, a subprogram library such as binding). "Co-encapsulation," as I like to call it, has a cost: Loss of abstraction. Because both types have visibility to each other's private features, there is no way to enforce each to adhere to the discipline of only calling the other's public interface. This affects understandability: Readers must understand what both types are doing, internally, before they can be sure they know what either type is doing. Of course, if it's just "a pair of abstract data types that are intimately related", and that's all there is to it, then the cost of abstraction-loss is relatively small, so co-encapsulation may be a reasonable option. But what if that's not all there is to it? Then the transitivity problem rears its ugly head: If class A is "intimately related" to class B, and class B is "intimately related" to class C, you may be forced to co-encapsulate A, B, and C, despite the fact that you did not envision any "intimate relationship" between A and C in your original software design. What if you've used an object-oriented analysis and design method, such as OMT or UML, to develop a model of your application domain comprised of a lot of classes linked together by a lot of binary associations? *Any* binary association might be construed as an "intimate relationship" between the two clases involved. But each class may be involved in several associations. And if your model is complete, I believe it should form a single contiguous graph of classes linked by associations, with no isolated islands. Under these circumstances, if you allow the transitivity effect to proceed unchecked, it can spread like a virus to infect your entire application. Robert Dewar hits on this problem: Robert Dewar wrote: > > ... -- it is really a natural > consequence of any domain in which recursion is an important idiom. > > For example, if we have a compiler with separate units to handle if statements > and loop statements, it is natural for if's to have loops and loops to have > if's. Surely you don't think this means that we have to put loops and if's > in the same unit -- because if you do you are syaing the whole compiler must > be one unit! Here, I take "recursion" to mean "recursive data structures," where an object of one type may contain references to objects of another type, and vice versa. I would go one step further: The transitivity problem doesn't just affect applications that involve this kind of recursion. *Any* binary association, conceived of during object-oriented analysis, is potentially vulnerable when you get to the design stage, and have to decide whether the association needs to be traversible in one direction, or the other, or both. A mutually-recursive data structure is just one way of implementing bidirectional traversals, but it's not the only way. It was this transitivity problem that prompted me to kick off that long thread a couple of years ago, and it was the seriousness of this problem, as I saw it, that prompted me to pursue that thread for so long. ------------------------------------------------------------------------ Internet.Usenet.Put_Signature (Name => "John G. Volan", Home_Email => "johnvolan@sprintmail.com", Slogan => "Ada95: The World's *FIRST* International-Standard OOPL", Disclaimer => "These opinions were never defined, so using them " & "would be erroneous...or is that just nondeterministic now? :-) "); ------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-29 0:00 ` John G. Volan @ 1997-04-29 0:00 ` Matthew Heaney 1997-04-30 0:00 ` Jon S Anthony ` (2 more replies) 0 siblings, 3 replies; 81+ messages in thread From: Matthew Heaney @ 1997-04-29 0:00 UTC (permalink / raw) In article <33660F4B.1B45@sprintmail.com>, johnvolan@sprintmail.com wrote: >> I'm talking about just a pair of abstract data types that are intimately >> related. But I sense that you and the other posters are talking about >> large packages (say, a subprogram library such as binding). > >"Co-encapsulation," as I like to call it, has a cost: Loss of >abstraction. Because both types have visibility to each other's private >features, there is no way to enforce each to adhere to the discipline of >only calling the other's public interface. This affects >understandability: Readers must understand what both types are doing, >internally, before they can be sure they know what either type is doing. > >Of course, if it's just "a pair of abstract data types that are >intimately related", and that's all there is to it, then the cost of >abstraction-loss is relatively small, so co-encapsulation may be a >reasonable option. That's all I was saying: a pair of ADTs that are intimately related. Here's an example. In order to efficiently implement an active iterator, that iterator has to have knowledge of the representation of the data structure. For a bounded stack, I would do this: type Bounded_Stack is new Root_Stack with private; type Bounded_Stack_Iterator (Stack : access Bounded_Stack) is new Root_Stack_Iterator with private; ... private subtype Item_Array_Range is Positive range 1 .. Size; type Item_Array is array (Item_Array_Range) of Stack_Item; type Bounded_Stack is new Root_Stack with record Items : Item_Array; Top : Natural := 0; end record; type Bounded_Stack_Iterator (Stack : access Bounded_Stack) is new Root_Stack_Iterator with record Index : Positive; end record; end Stacks_G.Bounded_G; I'm certainly not advocating large packages. It's just that very often, there are a small number of types (read: 2) that need to know about each other's representation, or that one needs the know the represenation of the other (the iterator above). This is just the concept of a friend in C++: to implement that in Ada, you put the types together in the same package. No big deal. There is NO loss of abstraction when the stack and its iterator are co-located in the same package; the abstractions were meant to be used together. I don't subscribe to these gloom and doom scenarios about putting types together; this is how the language was _intended_ to be used. And it's certainly true that this affects understandability: it makes it MORE understandable when the "declaration span" is minimized. This is analogous to using a declare block to move declaration of an object as close as possible to its use. I don't understand why a client needs to understand "internally" the Bounded_Stack and its iterator to use it: Do_Not_Need_Knowledge_Of_Representation_To_Use: declare The_Stack : aliased Bounded_Stack; The_Iterator : Bounded_Stack_Iterator (The_Stack'Access); begin ... while not Is_Done (The_Iterator) loop <process Current_Item (The_Iterator)> Advance (The_Iterator); end loop; end Do_Not_Need_Knowledge_Of_Representation_To_Use; What's so difficult about this? Matt -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-29 0:00 ` Matthew Heaney @ 1997-04-30 0:00 ` Jon S Anthony 1997-05-01 0:00 ` John G. Volan 1997-05-02 0:00 ` AQ&S Guidance on pragma Elaborate_Body John G. Volan 2 siblings, 0 replies; 81+ messages in thread From: Jon S Anthony @ 1997-04-30 0:00 UTC (permalink / raw) In article <mheaney-ya023680002904972043250001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes: > I'm certainly not advocating large packages. It's just that very often, > there are a small number of types (read: 2) that need to know about each > other's representation, or that one needs the know the represenation of the > other (the iterator above). > > This is just the concept of a friend in C++: to implement that in Ada, you > put the types together in the same package. No big deal. I disagree. "Friendship" typically has more to do with types that need *implementation* information about one another in order to be efficient. And it is not bi directional - no mutual dependence. This is almost always something that happens after the creation of one of the types - a new type is defined which utilizes another as a component [note: not as a parent class - that is handled by inheritance and protection]. In Ada this sort of thing is handled by child packages which can a) be defined way after the fact and b) still have direct information about the implementation of the used type. The notion of mutually dependent types is a very different thing altogether. In C++ this is handled (basically) via forward declarations. And there is no direct analog (capability) for this in Ada except incomplete types. But these require everything to be in the same _immediate_ scope. /Jon -- Jon Anthony Organon Motives, Inc. Belmont, MA 02178 617.484.3383 jsa@organon.com ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-29 0:00 ` Matthew Heaney 1997-04-30 0:00 ` Jon S Anthony @ 1997-05-01 0:00 ` John G. Volan 1997-05-02 0:00 ` Booch "forms" and child packages [was: AQ&S Guidance on pragma Elaborate_Body] John G. Volan 1997-05-02 0:00 ` AQ&S Guidance on pragma Elaborate_Body John G. Volan 2 siblings, 1 reply; 81+ messages in thread From: John G. Volan @ 1997-05-01 0:00 UTC (permalink / raw) Matthew Heaney wrote: > > In article <33660F4B.1B45@sprintmail.com>, johnvolan@sprintmail.com wrote: [snip] > >Of course, if it's just "a pair of abstract data types that are > >intimately related", and that's all there is to it, then the cost of > >abstraction-loss is relatively small, so co-encapsulation may be a > >reasonable option. > > That's all I was saying: a pair of ADTs that are intimately related. > Here's an example. In order to efficiently implement an active iterator, > that iterator has to have knowledge of the representation of the data > structure. [snip bounded stack & iterator code] > I'm certainly not advocating large packages. It's just that very often, > there are a small number of types (read: 2) that need to know about each > other's representation, or that one needs the know the represenation of the > other (the iterator above). > > This is just the concept of a friend in C++: to implement that in Ada, you > put the types together in the same package. No big deal. Um, sort of, but not exactly. Friendship isn't symmetrical: your friends can see your internals, but you can't see theirs (unless they grant you friendship in turn). Whereas co-encapsulation doesn't distinguish either party. The closest analog to friends in Ada95 is child packages -- but that's not an exact analogy either. More on this below... > There is NO loss of abstraction when the stack and its iterator are > co-located in the same package; There might not be any loss of abstraction from the point of view of some third-party client that uses both abstractions, but there _is_ a loss of abstraction _between_ the two types. For an isolated case like this, I admit the harm is small, and may be outweighed by other design issues ("declaration span", as you put it). But the fact remains that, once you choose to co-encapsulate them, the stack type and the iterator type are under no obligation to treat _each other_ as abstractions. > the abstractions were meant to be used together. Oh really? Always? In every conceivable application? What if there's an application that doesn't need to use stack iterators, but only needs some basic operations that work at the "whole-stack" level (e.g., push, pop)? Then the iterator stuff becomes extraneous. As you point out yourself, the relationship here is really just one-way: The iterator type needs to know about the implementation of the stack type, but the stack type can be implemented quite nicely without any notion of stack iterators. Rather than thinking of stacks and their iterators as two inseparable parts of a single abstraction, you could view stack iterators as an extension on the abstraction of stacks. This suggests that iterators might be better off in a _child_ package. The iterator type could still see the implementation details of the stack type, but the original stack package wouldn't be "cluttered" with this extra concept of an iterator. This way, iterators are optional: If an application needs them, it can "with" the child package; if it doesn't need them, it won't have to pay the cost of having the iterator code linked in. A child package is something like a friend, but not quite: A child can be declared after the fact without modifying the original parent package. The parent package doesn't have to mention the child (and essentially _can't_). But to become a friend of class X, this has to be mentioned in advance as part of the declaration of class X. If you decide you want to confer friendship later, you must modify your original class to do so. > I don't subscribe to these gloom and doom scenarios about > putting types together; this is how the language was _intended_ to be used. Hey, it's a general purpose language with a lot of features. It was "intended" to support a _variety_ of coding styles and idioms. > And it's certainly true that this affects understandability: it makes it > MORE understandable when the "declaration span" is minimized. But size and complexity also impact understandability: If you designate something as a "single indivisible unit of abstraction", the larger that unit happens to be, and the more pieces it contains, the more a user must digest, and the harder it is to understand in one sitting. Breaking things out into child packages allows the users take things in stages: They can look at the stack package first, in isolation, and understand how things work at the "whole-stack" level of granularity. Then later they can look at the iterator child package and tackle the concept of iterating over the stack at the finer, item-level of granularity. > I don't understand why a client needs to understand "internally" the > Bounded_Stack and its iterator to use it: If readers are presented with a package containing two abstract data types, then they are faced with the prospect of understanding the semantics of both ADTs together. If the package is well-documented, then the documentation will fully describe the outwardly-visible behavior of two ADTs, including how they might interact with each other. If the package is poorly-documented (as is so often the case), then readers will need to explore the package body, looking in detail at the code for both ADTs, before they can be satisfied they understand what either ADT is really all about. Documentation sometimes lies, or is obsolete, so users may need to pore over the body code anyway. Eventually, they might realize, for instance, that one of the ADTs is actually entirely independent of the other, but it may take some mental grinding before they can grok that. > This is > analogous to using a declare block to move declaration of an object as > close as possible to its use. I don't get this analogy at all -- in fact, I think it's more apt as an analogy for the _opposite_ position: You have a declaration X that is only needed in a local scope, so instead of declaring it in a more global scope along with Y, Z, and W (which might be somewhat related to X but are used more globally), you isolate X in its own a declare block. Similarly, you have an abstract data type X that you only need for special purposes under special circumstances, so instead of lumping it into the same package with Y, Z, and W (which might be somewhat related X but are used more generally), you isolate X in its own package (which might be a child package). ------------------------------------------------------------------------ Internet.Usenet.Put_Signature (Name => "John G. Volan", Home_Email => "johnvolan@sprintmail.com", Slogan => "Ada95: The World's *FIRST* International-Standard OOPL", Disclaimer => "These opinions were mever defined, so using them " & "would be erroneous...or is that just nondeterministic now? :-) "); ------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 81+ messages in thread
* Booch "forms" and child packages [was: AQ&S Guidance on pragma Elaborate_Body] 1997-05-01 0:00 ` John G. Volan @ 1997-05-02 0:00 ` John G. Volan 0 siblings, 0 replies; 81+ messages in thread From: John G. Volan @ 1997-05-02 0:00 UTC (permalink / raw) Apologies for following up my own post, but I had a thought: John G. Volan wrote: > > This suggests that iterators might be better off in a _child_ package. > The iterator type could still see the implementation details of the > stack type, but the original stack package wouldn't be "cluttered" with > this extra concept of an iterator. This way, iterators are optional: If > an application needs them, it can "with" the child package; if it > doesn't need them, it won't have to pay the cost of having the iterator > code linked in. One of the problems I had with the old Booch components was how Booch's notion of "forms" introduced so much duplication of code into his ADT library. For instance, one dimension of form Booch considered was whether an ADT package included support for iterators or not. For every package that did provided iterators, there would be another one that didn't. Often times both packages would be identical except for the iterator stuff. This must present something of a configuration nightmare if you're the maintainer of the ADT library. Multiply this by all the various "form" dimensions Booch identified, and you get a combinatorial explosion of slightly different versions. I can see why Booch had to do this: Features such as iterators are really optional, so clients ought to be allowed to select whether they want all that baggage included into their applications or not. In Ada83, with its flat library space, the only recourse was to have duplicate packages providing slightly different versions of the same ADT. In Ada95, you can avoid this problem (in some cases) by exploiting Ada95's hierarchical library space: For instance, as I described above, you can write a base ADT package without iterators, and then support the iterator concept in a child package. The iterator child package doesn't duplicate any code from the parent ADT package, it just adds whatever extra is needed to support this extra concept (and can exploit knowledge of the private implementation details of the ADT in order to do so). Yet this arrangement still gives clients all the flexibility they need: If they only need the base ADT, that's all they need to "with"; if they also need iterators, they can "with" the child package, too. ------------------------------------------------------------------------ Internet.Usenet.Put_Signature (Name => "John G. Volan", Home_Email => "johnvolan@sprintmail.com", Slogan => "Ada95: The World's *FIRST* International-Standard OOPL", Disclaimer => "These opinions were never defined, so using them " & "would be erroneous...or is that just nondeterministic now? :-) "); ------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-29 0:00 ` Matthew Heaney 1997-04-30 0:00 ` Jon S Anthony 1997-05-01 0:00 ` John G. Volan @ 1997-05-02 0:00 ` John G. Volan 2 siblings, 0 replies; 81+ messages in thread From: John G. Volan @ 1997-05-02 0:00 UTC (permalink / raw) Sorry to follow-up the same post twice, but: Matthew Heaney wrote: > > In article <33660F4B.1B45@sprintmail.com>, johnvolan@sprintmail.com wrote: ... > >Of course, if it's just "a pair of abstract data types that are > >intimately related", and that's all there is to it, then the cost of > >abstraction-loss is relatively small, so co-encapsulation may be a > >reasonable option. > > That's all I was saying: a pair of ADTs that are intimately related. But that's a straw man -- yes, sometimes there are isolated pairs of abstractions that are so tightly coupled to each other that they really do belong in the same package. I readily concede that possibility. But that's not what I was talking about when I said: > But what if that's not all there is to it? Then the transitivity > problem rears its ugly head: If class A is "intimately related" to class > B, and class B is "intimately related" to class C, you may be forced to > co-encapsulate A, B, and C, despite the fact that you did not envision > any "intimate relationship" between A and C in your original software > design. I was actually talking about situations where the coupling between classes was relatively loose: Let's just consider what happens in general when classes collaborate with each other through basic client-supplier relationships. Each class, in general, can be both a supplier of services to several other classes, and a client of the services of several other classes. As a supplier, each class should provide an abstract interface for its clients; as a client, each class should be happy to interact with its suppliers through their abstract interfaces. No client class should ever need to know anything about the internal details of its suppliers. That's what abstraction and encapsulation are all about. Now, in many cases, a class's set of clients and set of suppliers will be disjoint sets. But sometimes these two sets might just happen to overlap, and in the intersection a class may be treating another class both as a supplier and a client. In Ada95, this leads to a situation where two package bodies "with" each other's specs. Matthew, you argued that this was a warning sign that the classes in the two packages were "intimately related", constituting a single abstraction that ought to be co-encapsulated into a single package. Many have made this contention, especially in the early days of Ada83. But why should we make a distinction between one kind of client (or supplier) and another? As I've already pointed out, co-encapsulating such pairs of classes unnecessarily breaks down the abstraction barrier between them, and this effect can be transitively infective. There are, in fact, viable software designs where every class's client-set and supplier-set happens to be _identical_ -- i.e., _every_ association between classes gets implemented as a mutual, bidirectional client-supplier relationship. If we go with what you advocate, then such designs are doomed to be implemented as single, monolithic packages. If so, then what was the point of inventing packages in the first place? ------------------------------------------------------------------------ Internet.Usenet.Put_Signature (Name => "John G. Volan", Home_Email => "johnvolan@sprintmail.com", Slogan => "Ada95: The World's *FIRST* International-Standard OOPL", Disclaimer => "These opinions were never defined, so using them " & "would be erroneous...or is that just nondeterministic now? :-) "); ------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Jon S Anthony 1997-04-24 0:00 ` Matthew Heaney @ 1997-04-25 0:00 ` Robert Dewar 1 sibling, 0 replies; 81+ messages in thread From: Robert Dewar @ 1997-04-25 0:00 UTC (permalink / raw) <<Hmmm, you're probably about the only one left here that believes this. The "withing problem" (and this is for SPECS, not just the above sort of case) has been discussed here extensively and the general consensus is that this inability (to define mutually dependent types across package boundaries) is a hole in the language. The great maker himself, STT, has come to hold this position. BTW, anyone know whatever became of Tucker's proposal of "with package.type" for solving this?? I know it wasn't going to be "formally" accepted somehow, but wasn't there going to be some sort of general agreement to provide this? >> The best thing you could hope for is a general agreement on what it should look like if it is provided. Beyond that you have to let the market decide whether vendors should work on this. We have customers who are running into trouble with elaboration issues, which is why we have put work in on the elaboration problem, but so far, none of our customers have been willing to even request this feature, let alone offer to fund its development. Of course if several vendors implement it, then there is pressure for other vendors to follow suit, but it takes someone *really* interested to get a vendor to be the first. After all, we are all a little hesitant to get into the genuine language extension business! ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Matthew Heaney 1997-04-24 0:00 ` Robert Dewar 1997-04-24 0:00 ` Jon S Anthony @ 1997-04-24 0:00 ` Robert A Duff 1997-04-25 0:00 ` Michael F Brenner 3 siblings, 0 replies; 81+ messages in thread From: Robert A Duff @ 1997-04-24 0:00 UTC (permalink / raw) In article <mheaney-ya023680002404970907100001@news.ni.net>, Matthew Heaney <mheaney@ni.net> wrote: >It may be true that it "is not that uncommon," but mutual dependency of >packages indicates that you have a pair of highly cohesive abstractions, >and they should really be combined into a single package. I strongly disagree. Yes, they're highly cohesive (which is why one can tolerate Elab instead of Elab_All in these cases), but that doesn't mean you should always combine them. Consider a compiler (I always use compilers as examples, since that's what I do for a living): you might want to define a bunch of types representing pieces of syntax trees, and operations on those trees. Lots and lots of things will refer to "Expression_Ptr", and there are lots of kinds of expressions, and so forth, so your suggestion would require lumping just about everything into one package. This is because everything in the language definition is highly mutually recursive (statements contain expressions, expressions contain statements (in some languages), statements contain declarations, declarations contain statements, etc). I wish Ada 95 had *better* support for mutually recursive abstractions (remember that long thread of a year or two ago?) -- I certainly don't think mutually recursive packages are inherently evil. - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Matthew Heaney ` (2 preceding siblings ...) 1997-04-24 0:00 ` Robert A Duff @ 1997-04-25 0:00 ` Michael F Brenner 1997-04-26 0:00 ` Nick Roberts 3 siblings, 1 reply; 81+ messages in thread From: Michael F Brenner @ 1997-04-25 0:00 UTC (permalink / raw) >>A trivial example is two packages, each of whose bodies with's the others >>spec, which is not that uncommon. Obviously, those are NOT elaborable by a pre-elaborate, and that is why the more complicated elaboration pragmas exist. > It may be true that it "is not that uncommon," but mutual dependency of > packages indicates that you have a pair of highly cohesive abstractions, > and they should really be combined into a single package. It is my understanding that introduction of these highly cohesive structures is the only way in Ada 95 to simulate the feature that is really needed, namely having multiple, selectable bodies for the same generic visible part. This unfortunate situation comes about because non-generic packages cannot be passed as generic parameters. For example, in targetting multiple radar devices, I need to choose a (1) receive probabilistic pattern recognizer, (2) down converter, (3) selection criteria enhancer, (4) display driver, (5) embodied intelligence analysis component, (6) a boundary data structure, (7) geometry, (8) trigonometry (spherical or flat), (9) a topological model of the discontinuities in the antenna pattern, (10) a search strategy, (11) a viewing surface projection transformation, (12) and a conjugate image generator. It is easy to program this as a multiply cohesive hierarchical set of 12 packages each of which depends on the next higher level package in the partially ordered set, forming a giant circular dependency, and substituting them by recompiling, relinking, and re-running each time the user makes an alternate selection. However, without the ability to pass a non-generic package to a generic package, I do not know how to build this system without using these <Highly Cohesive Abstractions>. A simple cohesion metric based on variable access being more expensive at higher levels shows that this is, indeed, highly cohesive. In addition, the Ada-95 requirements to explicitly give bunches of elaboration pragmas proves beyond doubt how cohesive it is, even though Alsys Ada has no problem figuring out the correct elaboration order. Actually, that is not 100 percent fair, because the maintenance history of the project indicates that some changes were made that resulted in Alsys Ada figuring out the correct elaboration order, that is, some of the regression tests were removed from being executed in the regression test section at the bottom of some packages which were previously executed at elaboration time. Michael said: <<The goal should be that almost all of the non-thread-safe code should be marked ELABORATE_BODY, and almost all of the thread-safe code should be marked PREELABORATE or PURE.>> Robert said: <I have no idea what Michael has in mind here. This has nothing at all to do with thread safety. Elaboration and thread safety are entirely unrelated issues. In particular, a common idiom is to complete the elaboration before any tasks are started up.> The link between pragma pure and thread safety is that thread safety is a memory concern, and the concept of a pure package is to be memory-free, and therefore as thread safe as any code can be. That is why optimizers are permitted to optimize away multiple calls to procedures in pure packages--they have NO memory. If they had memory, and therefore potential thread-unsafeness, they ARE NOT pure, and it would be fibbing to mark them pure, and the optimized-away calls will be an undesireable effect on the execution of the code. The purity is transitive, since everything imported (withed) by a pure package must be pure. Therefore, if you call, for example, some pure_io.put_line several times during the debugging of a pure package, only the first pure_io.put_line would actually be called! The second, and all further calls to pure_io.put_line would generate no code (i.e., in DEC Vaxen Ada language, would be optimized away). By induction, all call from a pure package must be pure and therefore memory-less, and THEREFORE thread-safe, which is strictly a memory concern. The ONLY way something can be non-thread-safe is if two tasks change the same memory at the same time. Admittedly, we have to include non-purity to include memory erroneously generated by the compiler into the code that is on the heap or on a non-threaded stack, but we can assume that this is not an issue due to the quality of our compilers which correcly implement their stacks and have no cause to allocate anything on the heap for a PURE package, since there is NO DATA to allocate. While realtime systems normally do complete elaboration (and initialization, self-test, regression test, and build-in-test) before any task except the main task are started up, this has nothing to do with thread safety. Actually most realtime systems also allocate all tasks and variables at the beginning and avoid dynamic memory deallocations or allocations, but this is because of memory leakage, not thread safety. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-25 0:00 ` Michael F Brenner @ 1997-04-26 0:00 ` Nick Roberts 0 siblings, 0 replies; 81+ messages in thread From: Nick Roberts @ 1997-04-26 0:00 UTC (permalink / raw) Michael F Brenner <mfb@mbunix.mitre.org> wrote in article <5jq9uc$kuf@top.mitre.org>... > The link between pragma pure and thread safety is that thread safety is > a memory concern, and the concept of a pure package is to be memory-free, > and therefore as thread safe as any code can be. That is why optimizers > are permitted to optimize away multiple calls to procedures in pure > packages--they have NO memory. If they had memory, and therefore > potential thread-unsafeness, they ARE NOT pure, and it would be fibbing > to mark them pure, and the optimized-away calls will be an undesireable > effect on the execution of the code. The purity is transitive, since > everything imported (withed) by a pure package must be pure. Therefore, > if you call, for example, some pure_io.put_line several times during > the debugging of a pure package, only the first pure_io.put_line would > actually be called! > > The second, and all further calls to pure_io.put_line would generate no > code (i.e., in DEC Vaxen Ada language, would be optimized away). Surely it would be a 'very poor' (substitute your favourite expletive) compiler which 'optimized away' a second or subsequent call to a procedure with only 'in' parameters defined in a pure package (as in Michael's example)? Moreover (and much earlier), if a compiler were to come across a procedure which only has 'in' parameters declared in a pure package, surely to God it should give a big fat warning message? I don't know if the language (Ada 95) allows it, but it would really be best for the compiler to give up (with a fatal error), since this would certainly indicate a bug (wouldn't it?). Excellent post, by the way, Michael. Nick. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-18 0:00 AQ&S Guidance on pragma Elaborate_Body JP Thornley 1997-04-18 0:00 ` Robert A Duff 1997-04-18 0:00 ` Robert Dewar @ 1997-04-20 0:00 ` Doug Smith 1997-04-20 0:00 ` Robert Dewar 2 siblings, 1 reply; 81+ messages in thread From: Doug Smith @ 1997-04-20 0:00 UTC (permalink / raw) In article <528878564wnr@diphi.demon.co.uk>, jpt@diphi.demon.co.uk wrote: > In the rationale to Section 8.4.3, Coupling Due to Pragmas, the second > paragraph says:- > > "When there is a clear requirement for a recursive dependency, you > should use pragma Elaborate_Body. This situation arises, for example, > when you have a recursive dependency (i.e., package A's body depends on > package B's specification and package B's body depends on package A's > specification)." > > The most obvious interpretation of this is that the pragma should appear > in both packages - which will generate an error, probably at link/bind > time. > [snip] > Phil Thornley This was added in the '95 guidelines and I think is bad advice. This is in a section of the Quidelines for reusability, and was section 8.4.2 in the '83 Guidelines which recommended against pragma Elaborate for nongenerics. The only guideline which survived was "Use pragma Elaborate for generics named in a context clause." That could imply this paragraph was talking only of generics; however, generics cannot be mutually dependent (although instantiations can be mutually dependent in an indirect fashion). Doug <mailto:dsmith@clark.net> p.s. I see a new section 8.4.1 which reverts to the "Consider using..." phrases I tried to remove when editing the last '83 version. Rats! ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-20 0:00 ` Doug Smith @ 1997-04-20 0:00 ` Robert Dewar 1997-04-21 0:00 ` Matthew Heaney 0 siblings, 1 reply; 81+ messages in thread From: Robert Dewar @ 1997-04-20 0:00 UTC (permalink / raw) Doug said <<The only guideline which survived was "Use pragma Elaborate for generics named in a context clause." That could imply this paragraph was talking only of generics; however, generics cannot be mutually dependent (although instantiations can be mutually dependent in an indirect fashion).>> And this guideline is a poor one. You only need to use pragma Elaborate for generics named in the context clause if you instantiate the generic in your own elaboration code -- and furthermore, if you *do* such an instantiation, use Elaborate_All, not Elaborate -- and of course this only applies if the generic has a body! ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-20 0:00 ` Robert Dewar @ 1997-04-21 0:00 ` Matthew Heaney 1997-04-21 0:00 ` Robert A Duff 0 siblings, 1 reply; 81+ messages in thread From: Matthew Heaney @ 1997-04-21 0:00 UTC (permalink / raw) In article <dewar.861594771@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote: ><<The only guideline which survived was "Use pragma Elaborate for generics >named in a context clause." That could imply this paragraph was talking >only of generics; however, generics cannot be mutually dependent (although >instantiations can be mutually dependent in an indirect fashion).>> > >And this guideline is a poor one. You only need to use pragma Elaborate >for generics named in the context clause if you instantiate the generic >in your own elaboration code -- and furthermore, if you *do* such an >instantiation, use Elaborate_All, not Elaborate -- and of course this >only applies if the generic has a body! I don't understand. What do you mean by elaboration code? Is it defined as the package body, or only the begin part of the package body, ie with GQ; package body P is package Q is new GQ (...); end P; or this with GQ; package body P is begin declare package Q is new GQ (...); begin null; end; end P; Do either of these require pragma Elaborate (or Elaborate_All)? (Assume GQ does have a body.) And while I'm on the subject of pragma Elaborate, the Ada 83 RM stated that that pragma was only guarenteed to work when used on a predefined package such as Text_IO. Did this rule go away in Ada 95? Can I use pragma Elaborate freely, on user-defined library units, and have a guarentee that it will do something? Matt -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-21 0:00 ` Matthew Heaney @ 1997-04-21 0:00 ` Robert A Duff 1997-04-21 0:00 ` Robert Dewar 1997-04-21 0:00 ` Matthew Heaney 0 siblings, 2 replies; 81+ messages in thread From: Robert A Duff @ 1997-04-21 0:00 UTC (permalink / raw) In article <mheaney-ya023680002104970117080001@news.ni.net>, Matthew Heaney <mheaney@ni.net> wrote: >In article <dewar.861594771@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote: >>And this guideline is a poor one. You only need to use pragma Elaborate >>for generics named in the context clause if you instantiate the generic >>in your own elaboration code ...which is almost always the case, in my experience... >... -- and furthermore, if you *do* such an >>instantiation, use Elaborate_All, not Elaborate Agreed. Always use ELaborate_All instead of Elaborate, except when mutual recursion forces you to use Elaborate. (And, of course, use Pure, Preelaborate, or Elaborate_Body in preference to either Elab or Elab_All.) >... -- and of course this >>only applies if the generic has a body! It's best to assume that the generic has a body. The client shouldn't have to care. >I don't understand. What do you mean by elaboration code? Is it defined >as the package body, or only the begin part of the package body, ie > >with GQ; >package body P is > > package Q is new GQ (...); > >end P; > >or this > >with GQ; >package body P is >begin > declare > package Q is new GQ (...); > begin > null; > end; >end P; > >Do either of these require pragma Elaborate (or Elaborate_All)? (Assume GQ >does have a body.) Both of them do, since the instantiation is elaborated during the elaboration of P. On the other hand, if P contained: procedure Foo is package Q is new GQ... then you don't need the pragma. >And while I'm on the subject of pragma Elaborate, the Ada 83 RM stated that >that pragma was only guarenteed to work when used on a predefined package >such as Text_IO. That's a strange way to put it. Pragma Elaborate, in Adas 83 and 95, is not transitive, which is a pain, and which is why Elaborate_All was invented. It is true that Text_IO has to "work", despite the fact that pragma Elaborate is not very helpful in making it work (if Text_IO's body calls some other implementation-defined package that clients don't know about). >... Did this rule go away in Ada 95? Can I use pragma >Elaborate freely, on user-defined library units, and have a guarentee that >it will do something? The semantics of Elaborate has not changed. It will "do something" for user-defined library units -- it's just that that something is rather unhelpful. (That is, if R calls something in Q.Foo during elaboration, and Q.Foo calls somthing in P, then your abstraction is violated -- to put in exactly the "right" pragma Elaborates, either Q needs to know about its clients, or R needs to know about Q's implementation in terms of P. An Elaborate_All(Q) on R solves the problem, because it magically applies to P without R knowing about P.) - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-21 0:00 ` Robert A Duff @ 1997-04-21 0:00 ` Robert Dewar 1997-04-22 0:00 ` Robert A Duff 1997-04-21 0:00 ` Matthew Heaney 1 sibling, 1 reply; 81+ messages in thread From: Robert Dewar @ 1997-04-21 0:00 UTC (permalink / raw) iRobert Duff said <<...which is almost always the case, in my experience...>> I don't think so at all, I often see generics instantiated in an inner scope, there is absolutely no reason to consider this somehow poor style -- on the contrary, it is better to instantiate the generic as locally as possible -- the normal rule for declarations ... <<<<It's best to assume that the generic has a body. The client shouldn't have to care.>> >> I don't see any reason to assume that a generic has a body, when you can tell from the spec that it is not allowed to have a body -- well at least you can tell if there is no private part ... ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-21 0:00 ` Robert Dewar @ 1997-04-22 0:00 ` Robert A Duff 1997-04-24 0:00 ` Robert Dewar 0 siblings, 1 reply; 81+ messages in thread From: Robert A Duff @ 1997-04-22 0:00 UTC (permalink / raw) In article <dewar.861656614@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: >iRobert Duff said > ><<...which is almost always the case, in my experience...>> > > >I don't think so at all, I often see generics instantiated in an >inner scope, there is absolutely no reason to consider this somehow >poor style -- on the contrary, it is better to instantiate the generic >as locally as possible -- the normal rule for declarations ... I didn't say it was poor style, and I agree with "as locally as possible". But, in my experience, that usually ends up being in a library package, or *as* a library package. ><<<<It's best to assume that the generic has a body. The client shouldn't > have to care.>> >>> > >I don't see any reason to assume that a generic has a body, when you can >tell from the spec that it is not allowed to have a body -- well at least >you can tell if there is no private part ... Because somebody might change the generic to have a body, and then all the clients would be broken. Anyway, if the generic is nested in a package, you can't tell whether it has a body, so it's best to assume that it does. - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-22 0:00 ` Robert A Duff @ 1997-04-24 0:00 ` Robert Dewar 0 siblings, 0 replies; 81+ messages in thread From: Robert Dewar @ 1997-04-24 0:00 UTC (permalink / raw) <<I didn't say it was poor style, and I agree with "as locally as possible". But, in my experience, that usually ends up being in a library package, or *as* a library package.>> Well I can say that our regressoin suite has many hundreds of counter examples! ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-21 0:00 ` Robert A Duff 1997-04-21 0:00 ` Robert Dewar @ 1997-04-21 0:00 ` Matthew Heaney 1997-04-21 0:00 ` Matthew Heaney 1997-04-21 0:00 ` Robert A Duff 1 sibling, 2 replies; 81+ messages in thread From: Matthew Heaney @ 1997-04-21 0:00 UTC (permalink / raw) In article <E8znzn.DM2@world.std.com>, bobduff@world.std.com (Robert A Duff) wrote: >In article <mheaney-ya023680002104970117080001@news.ni.net>, >Matthew Heaney <mheaney@ni.net> wrote: >>In article <dewar.861594771@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote: >>>And this guideline is a poor one. You only need to use pragma Elaborate >>>for generics named in the context clause if you instantiate the generic >>>in your own elaboration code > >...which is almost always the case, in my experience... > >>... -- and furthermore, if you *do* such an >>>instantiation, use Elaborate_All, not Elaborate > >Agreed. Always use ELaborate_All instead of Elaborate, except when >mutual recursion forces you to use Elaborate. (And, of course, use >Pure, Preelaborate, or Elaborate_Body in preference to either Elab or >Elab_All.) OK, just so I understand this perfectly: If the generic package has used one of the pragmas Pure, Preelaborate, or Elaborate_Body, does that mean I the instantiator do not have to use pragma Elaborate_All? generic ... package GQ is pragma Pure; ... end GQ; with GQ; <<<--- No pragma Elaborate_All required, right? package P is package Q is new GQ (...); end P; Matt -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-21 0:00 ` Matthew Heaney @ 1997-04-21 0:00 ` Matthew Heaney 1997-04-22 0:00 ` Robert A Duff ` (2 more replies) 1997-04-21 0:00 ` Robert A Duff 1 sibling, 3 replies; 81+ messages in thread From: Matthew Heaney @ 1997-04-21 0:00 UTC (permalink / raw) In article <mheaney-ya023680002104970942110001@news.ni.net>, mheaney@ni.net (Matthew Heaney) wrote: >> >>>... -- and furthermore, if you *do* such an >>>>instantiation, use Elaborate_All, not Elaborate >> >>Agreed. Always use ELaborate_All instead of Elaborate, except when >>mutual recursion forces you to use Elaborate. (And, of course, use >>Pure, Preelaborate, or Elaborate_Body in preference to either Elab or >>Elab_All.) OK, one more question. Why not just pragma Elaborate? If I only instantiate the generic in the package declarative region, and do not call any of its functions during elaboration or initialization, then why pragma Elaborate_All? All I the instantiator require is the generic's body, not the bodies of the packages it with's, so isn't Elaborate good enough? -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-21 0:00 ` Matthew Heaney @ 1997-04-22 0:00 ` Robert A Duff 1997-04-22 0:00 ` Matthew Heaney 1997-04-22 0:00 ` Mats Weber 1997-04-23 0:00 ` Robert Dewar 2 siblings, 1 reply; 81+ messages in thread From: Robert A Duff @ 1997-04-22 0:00 UTC (permalink / raw) In article <mheaney-ya023680002104972250240001@news.ni.net>, Matthew Heaney <mheaney@ni.net> wrote: >OK, one more question. Why not just pragma Elaborate? If I only >instantiate the generic in the package declarative region, and do not call >any of its functions during elaboration or initialization, then why pragma >Elaborate_All? All I the instantiator require is the generic's body, not >the bodies of the packages it with's, so isn't Elaborate good enough? You can't tell without looking at the body of that generic (which is the root of this whole problem): generic package G1 is ... end G1; package body G1 is ... end G1; generic package G2 is ... end G2; with G1; package body G2 is package Inst_1 is new G1; end G2; with G2; pragma Elaborate(G2); package P is package Inst_2 is new G2; end P; This will raise Program_Error. - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-22 0:00 ` Robert A Duff @ 1997-04-22 0:00 ` Matthew Heaney 1997-04-22 0:00 ` Robert A Duff 1997-04-24 0:00 ` Robert Dewar 0 siblings, 2 replies; 81+ messages in thread From: Matthew Heaney @ 1997-04-22 0:00 UTC (permalink / raw) In article <E91Gty.4DI@world.std.com>, bobduff@world.std.com (Robert A Duff) wrote: > generic > package G1 is ... end G1; > > package body G1 is ... end G1; > > generic > package G2 is ... end G2; > > with G1; > package body G2 is > package Inst_1 is new G1; > end G2; > > with G2; pragma Elaborate(G2); > package P is > package Inst_2 is new G2; > end P; > >This will raise Program_Error. But isn't G2 supposed to elaborate G1? with G1; pragma Elaborate (G1); <<<--- package body G2 is package Inst_1 is new G1; end G2; Isn't G2 supposed to take care of it's own business, and make sure G1 is elaborated? This is analogous to P making sure G2 is elaborated. Matt -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-22 0:00 ` Matthew Heaney @ 1997-04-22 0:00 ` Robert A Duff 1997-04-22 0:00 ` Matthew Heaney 1997-04-24 0:00 ` Robert Dewar 1 sibling, 1 reply; 81+ messages in thread From: Robert A Duff @ 1997-04-22 0:00 UTC (permalink / raw) (e-mailed and posted) In article <mheaney-ya023680002204970735480001@news.ni.net>, Matthew Heaney <mheaney@ni.net> wrote: >In article <E91Gty.4DI@world.std.com>, bobduff@world.std.com (Robert A >Duff) wrote: > >> generic >> package G1 is ... end G1; >> >> package body G1 is ... end G1; >> >> generic >> package G2 is ... end G2; >> >> with G1; >> package body G2 is >> package Inst_1 is new G1; >> end G2; >> >> with G2; pragma Elaborate(G2); >> package P is >> package Inst_2 is new G2; >> end P; >> >>This will raise Program_Error. > >But isn't G2 supposed to elaborate G1? > >with G1; >pragma Elaborate (G1); <<<--- >package body G2 is > package Inst_1 is new G1; >end G2; No, G2 does not instantiate G1 during its (G2's) elaboration. In fact, G2 doesn't do anything during elaboration, except to record the fact that it has now been elaborated. In the above example, the following elaboration order does not raise P_E: G2 spec G2 body G1 spec G1 body P spec Of course, you can have a convention that calls for putting in unnecessary pragmas Elaborate, such as the one you suggest. (For example, a reasonable convention for Ada 83 was: put pragma Elaborate on everything you "with", unless you can't because of a cycle.) But I thought we were discussing this convention: X should have pragma-Elaborate_All of Y if and only if X calls/instantiates/activates some subprogram/generic/task in Y during X's elaboration (unless Y has Pure, Preelab, or Elab_Body). And you asked, with respect to this convention, whether it should be Elab instead of Elab_Body. >Isn't G2 supposed to take care of it's own business, and make sure G1 is >elaborated? This is analogous to P making sure G2 is elaborated. No, it's not analogous. G2 is instantiated during P's elaboration. G1 is not instantiated during G2's elaboration. - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-22 0:00 ` Robert A Duff @ 1997-04-22 0:00 ` Matthew Heaney 1997-04-23 0:00 ` Robert A Duff 1997-04-23 0:00 ` Robert Dewar 0 siblings, 2 replies; 81+ messages in thread From: Matthew Heaney @ 1997-04-22 0:00 UTC (permalink / raw) In article <E91yH8.36E@world.std.com>, bobduff@world.std.com (Robert A Duff) wrote: >>But isn't G2 supposed to elaborate G1? >> >>with G1; >>pragma Elaborate (G1); <<<--- >>package body G2 is >> package Inst_1 is new G1; >>end G2; > >No, G2 does not instantiate G1 during its (G2's) elaboration. In fact, >G2 doesn't do anything during elaboration, except to record the fact >that it has now been elaborated. > >But I >thought we were discussing this convention: X should have >pragma-Elaborate_All of Y if and only if X calls/instantiates/activates >some subprogram/generic/task in Y during X's elaboration (unless Y has >Pure, Preelab, or Elab_Body). And you asked, with respect to this >convention, whether it should be Elab instead of Elab_Body. OK, I almost understand. The elaboration of the generic itself is not very interesting: it's the elaboration of the instantiation that we need to think about carefully. The rules go like this: Why You Need Pragma Elaborate_All And Not Just Elaborate o An instantiation of a generic inside another generic (package) isn't really elaborated until the elaboration of the instantiation of the enclosing generic. So that's why we need pragma Elaborate_All and not just pragma Elaborate. o If you call a subprogram of a package you with'd during your elaboration, you need to pragma Elaborate_All, to cover elaboration of library units in the called subprogram. I think I've got it. Thank you, Bob, once again... Matt -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-22 0:00 ` Matthew Heaney @ 1997-04-23 0:00 ` Robert A Duff 1997-04-24 0:00 ` Matthew Heaney 1997-04-25 0:00 ` Robert Dewar 1997-04-23 0:00 ` Robert Dewar 1 sibling, 2 replies; 81+ messages in thread From: Robert A Duff @ 1997-04-23 0:00 UTC (permalink / raw) In article <mheaney-ya023680002204972039270001@news.ni.net>, Matthew Heaney <mheaney@ni.net> wrote: > Why You Need Pragma Elaborate_All And Not Just Elaborate > >o An instantiation of a generic inside another generic (package) isn't >really elaborated until the elaboration of the instantiation of the >enclosing generic. So that's why we need pragma Elaborate_All and not just >pragma Elaborate. > >o If you call a subprogram of a package you with'd during your >elaboration, you need to pragma Elaborate_All, to cover elaboration of >library units in the called subprogram. Right. In practice, this leads to the simple rule: Always use Elaborate_All instead of Elaborate, except when you can't. "When you can't" means there's some sort of mutual recursion going on, and you have to use Elaborate instead. - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-23 0:00 ` Robert A Duff @ 1997-04-24 0:00 ` Matthew Heaney 1997-04-24 0:00 ` Robert A Duff 1997-04-25 0:00 ` Robert Dewar 1 sibling, 1 reply; 81+ messages in thread From: Matthew Heaney @ 1997-04-24 0:00 UTC (permalink / raw) In article <E9415t.8z9@world.std.com>, bobduff@world.std.com (Robert A Duff) wrote: >In practice, this leads to the simple rule: Always use Elaborate_All >instead of Elaborate, except when you can't. "When you can't" means >there's some sort of mutual recursion going on, and you have to use >Elaborate instead. OK, just one more mint, wafer thin... What should the instantiator do if the generic has a pragma Pure, Preelab, or Elab_Body? Does the instantiator still have to pragma Elaborate_All the generic package? Or can he omit that pragma? Can you explain when exactly does the pragma Pure of the generic package apply? During elaboration of the generic, or of the instantiation? M. -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Matthew Heaney @ 1997-04-24 0:00 ` Robert A Duff 0 siblings, 0 replies; 81+ messages in thread From: Robert A Duff @ 1997-04-24 0:00 UTC (permalink / raw) In article <mheaney-ya023680002404970055380001@news.ni.net>, Matthew Heaney <mheaney@ni.net> wrote: >What should the instantiator do if the generic has a pragma Pure, Preelab, >or Elab_Body? Does the instantiator still have to pragma Elaborate_All the >generic package? Or can he omit that pragma? Elab_All can be omitted in this case, which is one reason why Pure, Preelab, and Elab_Body are so convenient. (Robert has pointed out how to put debugging statements in Pure units -- if you're not using GNAT, you can cheat in a similar way by calling some pragma-Imported thing -- which I suppose could be written in Ada.) >Can you explain when exactly does the pragma Pure of the generic package >apply? During elaboration of the generic, or of the instantiation? The generic. If you want the instance to be pure, you have to put the pragma on the instance (if its a lib unit), or on the containing lib unit. This last is not obvious from the RM -- there's an AI on this issue. - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-23 0:00 ` Robert A Duff 1997-04-24 0:00 ` Matthew Heaney @ 1997-04-25 0:00 ` Robert Dewar 1 sibling, 0 replies; 81+ messages in thread From: Robert Dewar @ 1997-04-25 0:00 UTC (permalink / raw) Bob said <<In practice, this leads to the simple rule: Always use Elaborate_All instead of Elaborate, except when you can't. "When you can't" means there's some sort of mutual recursion going on, and you have to use Elaborate instead.>> This is definitely an appropriate rule. In fact for a while, the design team had the view that this rule was so widely applicable that they consigned pragma Elaborate to Annex J (the dreaded obsolescent feature pile). But I found a few examples (from the GNAT runtime actually) that] convinced us to keep pragma Elaborate as a first class citizen. Still it is very rarely appropriate to use it. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-22 0:00 ` Matthew Heaney 1997-04-23 0:00 ` Robert A Duff @ 1997-04-23 0:00 ` Robert Dewar 1 sibling, 0 replies; 81+ messages in thread From: Robert Dewar @ 1997-04-23 0:00 UTC (permalink / raw) Matthew Heaney said <<OK, I almost understand. The elaboration of the generic itself is not very interesting: it's the elaboration of the instantiation that we need to think about carefully. The rules go like this:>> your statement of the rules is not quite complete, but is essentially right. The elaboration of the generic itself is entirely analogous to the elaboration of a subprogram. It is not completely a noop, because of the fundamental rule that you cannot instantiate a generic (call a subprogram) until the body of the generic is elaborated (the body of the subprogram is elaborated). Typically the code corresponding to the elaboration of a generic is to set a flag that will be tested on instantiations (to make sure that it is set). ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-22 0:00 ` Matthew Heaney 1997-04-22 0:00 ` Robert A Duff @ 1997-04-24 0:00 ` Robert Dewar 1997-04-24 0:00 ` Robert A Duff 1 sibling, 1 reply; 81+ messages in thread From: Robert Dewar @ 1997-04-24 0:00 UTC (permalink / raw) Responding To Bob Duff's example generic package G1 is ... end G1; package body G1 is ... end G1; generic package G2 is ... end G2; with G1; package body G2 is package Inst_1 is new G1; end G2; with G2; pragma Elaborate(G2); package P is package Inst_2 is new G2; end P; Matthew Heaney asks But isn't G2 supposed to elaborate G1? with G1; pragma Elaborate (G1); <<<--- package body G2 is package Inst_1 is new G1; end G2; Isn't G2 supposed to take care of it's own business, and make sure G1 is elaborated? This is analogous to P making sure G2 is elaborated. Robert Dewar replies In general the answer is no. G2 has no elaboration problem (generic packages themselves require nothing to be elaborated). It is the instance of G2 that might need elaboration. If no one ever instantiates G2 in elaboration code, then there is absolutely no need to elaborate the body of G1 before the spec of G2. This requirement comes from the fact that P instantiates G2 at elaboration time. Thus P must take responsibility for the elaboration, and do a pragma Elaborate_All, rather than a pragma Elaborate. Note: This is exactly the kind of automatic Elaborate_All that the new version of GNAT does by default. It will also on request output warnings for missing Elaborate_All pragmas. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-24 0:00 ` Robert Dewar @ 1997-04-24 0:00 ` Robert A Duff 0 siblings, 0 replies; 81+ messages in thread From: Robert A Duff @ 1997-04-24 0:00 UTC (permalink / raw) In article <dewar.861864497@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: >Note: This is exactly the kind of automatic Elaborate_All that the new >version of GNAT does by default. It will also on request output warnings >for missing Elaborate_All pragmas. That's interesting. Can you describe exactly what cases cause a warning? - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-21 0:00 ` Matthew Heaney 1997-04-22 0:00 ` Robert A Duff @ 1997-04-22 0:00 ` Mats Weber 1997-04-23 0:00 ` Robert Dewar 2 siblings, 0 replies; 81+ messages in thread From: Mats Weber @ 1997-04-22 0:00 UTC (permalink / raw) > OK, one more question. Why not just pragma Elaborate? If I only > instantiate the generic in the package declarative region, and do not call > any of its functions during elaboration or initialization, then why pragma > Elaborate_All? All I the instantiator require is the generic's body, not > the bodies of the packages it with's, so isn't Elaborate good enough? Because if your generic instantiates another generic in its body or spec (a very common siutation), then you must include a pragma Elaborate for that other generic too, and therefore also a with clause for it, which you don't want. You can find a discussion of the elaboration problems in Ada in my PhD thesis at <http://lglwww.epfl.ch/Team/MW/Ada-Extensions/Ada-Extensions.html> sections 2.7 and 4.5. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-21 0:00 ` Matthew Heaney 1997-04-22 0:00 ` Robert A Duff 1997-04-22 0:00 ` Mats Weber @ 1997-04-23 0:00 ` Robert Dewar 2 siblings, 0 replies; 81+ messages in thread From: Robert Dewar @ 1997-04-23 0:00 UTC (permalink / raw) Matthew Heaney asks <<OK, one more question. Why not just pragma Elaborate? If I only instantiate the generic in the package declarative region, and do not call any of its functions during elaboration or initialization, then why pragma Elaborate_All? All I the instantiator require is the generic's body, not the bodies of the packages it with's, so isn't Elaborate good enough?>> Because the body may have elaboration code that calls functions in units that are with'ed by the generic and not by the client. Incidentally, I find that the whole elaboration issue is one on which a lot of people are fuzzy. I am currently doing a complete documentation section on the new GNAT support for elaboration checking and management, and that section also tries to explain the technical aspects of this issue. ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-21 0:00 ` Matthew Heaney 1997-04-21 0:00 ` Matthew Heaney @ 1997-04-21 0:00 ` Robert A Duff 1 sibling, 0 replies; 81+ messages in thread From: Robert A Duff @ 1997-04-21 0:00 UTC (permalink / raw) In article <mheaney-ya023680002104970942110001@news.ni.net>, Matthew Heaney <mheaney@ni.net> wrote: >OK, just so I understand this perfectly: If the generic package has used >one of the pragmas Pure, Preelaborate, or Elaborate_Body, does that mean I >the instantiator do not have to use pragma Elaborate_All? Yes. - Bob ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body @ 1997-04-30 0:00 W. Wesley Groleau (Wes) 1997-04-30 0:00 ` Robert I. Eachus 0 siblings, 1 reply; 81+ messages in thread From: W. Wesley Groleau (Wes) @ 1997-04-30 0:00 UTC (permalink / raw) The suggestion seemed to be making it less likely to crash a program due to elaboration order problems. The answer was that it would cause serious incompatibilities in legacy code. Tell me I didn't understand the suggestion, or I didn't understand the answer, or even tell me I'm very confused... but please clarify, because it sure looks like (to me) that this says it's a serious incompatibility for a program to run that could not run before. --------------------------------------------------------------------------- W. Wesley Groleau (Wes) Office: 219-429-4923 Hughes Defense Communications (MS 10-41) Home: 219-471-7206 Fort Wayne, IN 46808 (Unix): wwgrol@pseserv3.fw.hac.com -- SPAM should be sent to I.want.one@mailbombs.for.idiots.org If you want to be prosecuted under 27 USC 227, go ahead and send it here. --------------------------------------------------------------------------- ^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: AQ&S Guidance on pragma Elaborate_Body 1997-04-30 0:00 W. Wesley Groleau (Wes) @ 1997-04-30 0:00 ` Robert I. Eachus 0 siblings, 0 replies; 81+ messages in thread From: Robert I. Eachus @ 1997-04-30 0:00 UTC (permalink / raw) In article <9704301359.AA06917@most> "W. Wesley Groleau (Wes)" <wwgrol@PSESERV3.FW.HAC.COM> writes: > The suggestion seemed to be making it less likely to crash a program > due to elaboration order problems. The answer was that it would cause > serious incompatibilities in legacy code. > Tell me I didn't understand the suggestion, or I didn't understand the > answer, or even tell me I'm very confused... but please clarify, because > it sure looks like (to me) that this says it's a serious incompatibility > for a program to run that could not run before. You may not have understood, although the discussion did wander a little. The compatibility problem is that if you replace the current dynamic rule with a static rule, you either remove some dependency rules or replace them with others. Then either programs that are now legal with some elaboration order would have new legal elaboration orders, or programs which are now legal would be illegal. In the first case, if the compiler happened to choose one of these orders--and remember the original order may now be illegal--then you have an upward incompatibility. How serious an incompatibility? Don't know, it would depend on the rules. But due to the halting problem mapping, we know that they would have to be different in some way. In the second case, the problem of undetected errors wouldn't occur, but you would have existing (and often large) programs that would not legally link. How big an issue? Even one major program that required a major software redesign would probably be an unacceptable incompatibility. And since, as I said, I know of existing DoD software programs that would almost certainly fall in this category, this option is unacceptable. You may think that programs which read config files during elaboration and need a specific elaboration order that matches the content of those files is horrible design. I agree, but I am talking reality here, not best practice. (And in the actual I know of, it is not as bad as it sounds--a client/server system where the clients require one elaboration order and the server requires another. The clients and the server have different main programs, but you do have library packages which differ only in the elaboration pragmas. Clients and server are two different CSCIs.) -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 81+ messages in thread
end of thread, other threads:[~1997-05-02 0:00 UTC | newest] Thread overview: 81+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 1997-04-18 0:00 AQ&S Guidance on pragma Elaborate_Body JP Thornley 1997-04-18 0:00 ` Robert A Duff 1997-04-21 0:00 ` Michael F Brenner 1997-04-22 0:00 ` Robert A Duff 1997-04-18 0:00 ` Robert Dewar 1997-04-19 0:00 ` Michael Paus 1997-04-19 0:00 ` Robert A Duff 1997-04-21 0:00 ` Robert Dewar 1997-04-23 0:00 ` Robert A Duff 1997-04-23 0:00 ` Robert Dewar 1997-04-24 0:00 ` Robert A Duff 1997-04-24 0:00 ` Robert Dewar 1997-04-24 0:00 ` Robert Dewar 1997-04-25 0:00 ` Robert A Duff 1997-04-25 0:00 ` Mats Weber 1997-04-25 0:00 ` Robert I. Eachus 1997-04-26 0:00 ` Nick Roberts 1997-04-26 0:00 ` Robert Dewar 1997-04-28 0:00 ` Robert I. Eachus 1997-04-29 0:00 ` Robert Dewar 1997-04-29 0:00 ` Robert I. Eachus 1997-04-27 0:00 ` Robert Dewar 1997-04-28 0:00 ` Mats Weber 1997-04-29 0:00 ` Redefinition of "=", elaboration and learning Ada Mats Weber 1997-04-29 0:00 ` Robert A Duff 1997-04-30 0:00 ` Mats Weber 1997-04-26 0:00 ` AQ&S Guidance on pragma Elaborate_Body Nick Roberts 1997-04-26 0:00 ` Robert Dewar 1997-04-24 0:00 ` Mats Weber 1997-04-24 0:00 ` Robert A Duff 1997-04-24 0:00 ` Robert Dewar 1997-04-25 0:00 ` Robert Dewar 1997-04-20 0:00 ` Robert Dewar 1997-04-21 0:00 ` Michael F Brenner 1997-04-23 0:00 ` Robert Dewar 1997-04-24 0:00 ` Laurent Guerby 1997-04-24 0:00 ` Matthew Heaney 1997-04-24 0:00 ` Robert Dewar 1997-04-24 0:00 ` Jon S Anthony 1997-04-24 0:00 ` Matthew Heaney 1997-04-26 0:00 ` Nick Roberts 1997-04-26 0:00 ` Robert A Duff 1997-04-26 0:00 ` Matthew Heaney 1997-04-26 0:00 ` Robert Dewar 1997-04-26 0:00 ` Matthew Heaney 1997-04-27 0:00 ` Robert Dewar 1997-04-29 0:00 ` John G. Volan 1997-04-29 0:00 ` Matthew Heaney 1997-04-30 0:00 ` Jon S Anthony 1997-05-01 0:00 ` John G. Volan 1997-05-02 0:00 ` Booch "forms" and child packages [was: AQ&S Guidance on pragma Elaborate_Body] John G. Volan 1997-05-02 0:00 ` AQ&S Guidance on pragma Elaborate_Body John G. Volan 1997-04-25 0:00 ` Robert Dewar 1997-04-24 0:00 ` Robert A Duff 1997-04-25 0:00 ` Michael F Brenner 1997-04-26 0:00 ` Nick Roberts 1997-04-20 0:00 ` Doug Smith 1997-04-20 0:00 ` Robert Dewar 1997-04-21 0:00 ` Matthew Heaney 1997-04-21 0:00 ` Robert A Duff 1997-04-21 0:00 ` Robert Dewar 1997-04-22 0:00 ` Robert A Duff 1997-04-24 0:00 ` Robert Dewar 1997-04-21 0:00 ` Matthew Heaney 1997-04-21 0:00 ` Matthew Heaney 1997-04-22 0:00 ` Robert A Duff 1997-04-22 0:00 ` Matthew Heaney 1997-04-22 0:00 ` Robert A Duff 1997-04-22 0:00 ` Matthew Heaney 1997-04-23 0:00 ` Robert A Duff 1997-04-24 0:00 ` Matthew Heaney 1997-04-24 0:00 ` Robert A Duff 1997-04-25 0:00 ` Robert Dewar 1997-04-23 0:00 ` Robert Dewar 1997-04-24 0:00 ` Robert Dewar 1997-04-24 0:00 ` Robert A Duff 1997-04-22 0:00 ` Mats Weber 1997-04-23 0:00 ` Robert Dewar 1997-04-21 0:00 ` Robert A Duff -- strict thread matches above, loose matches on Subject: below -- 1997-04-30 0:00 W. Wesley Groleau (Wes) 1997-04-30 0:00 ` Robert I. Eachus
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox