From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,29e947df2e56cc40 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2002-07-31 13:39:38 PST Newsgroups: comp.lang.ada Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!news-spur1.maxwell.syr.edu!news.maxwell.syr.edu!upp1.onvoy!onvoy.com!news-out.visi.com!hermes.visi.com!uunet!ash.uu.net!world!news From: Robert A Duff Subject: Re: What's it's name again? Sender: news@world.std.com (Mr Usenet Himself) Message-ID: Date: Wed, 31 Jul 2002 20:38:42 GMT References: <8sickuks7ravfjr0hknush4ua0iu5h8t66@4ax.com> NNTP-Posting-Host: shell01.theworld.com Organization: The World Public Access UNIX, Brookline, MA X-Newsreader: Gnus v5.7/Emacs 20.7 Xref: archiver1.google.com comp.lang.ada:27534 Date: 2002-07-31T20:38:42+00:00 List-Id: Dmitry A.Kazakov writes: > > I'm not sure which part you think is hard. You could put procedure > > bodies in specs (like in C++) and make inlining easier. > > C++ is awful! All that idiotic rules that inlined function are compiled as > if all class declarations were appear before the function body. Then header > files of 1K+ lines long ... I'm not familiar with the details of these rules. I'm willing to believe that they are awful. > I see, but there is also a difference. The body of a subroutine is not a > part of its declaration, so you can continue compilation of specifications > no matter how the body looks like. Not if you're trying to inline the code. >... In contrary to this the size of a type > is a function of its declaration. So there might be no difference when some > other comilation unit is being compiled, but for a compilation the > package's specification I think there is a difference. I don't see any difference, in principle. If the compiler doesn't know the size of the type, it has to generate less efficient code. > > Here are the solutions that come to mind: > > > > 1. Make the private information part of the spec. This is what Ada does > > for private types -- the compiler can see the full type declaration. > > This is also what C++ uses for the inlined-call case: to inline > > something, you include the "body" in the "spec" of the class. > > (Please correct me if my memory of C++ is hazy.) > > Something like: > > package ... is > ... > procedure Foo; -- To be inlined (no extra pragma) > ... > private > ... > procedure Foo is -- Implementation here > begin > ... > end Foo; > ... Yes, something like that. This is essentially what C++ does for inlining. > There is a problem that Foo will see no package body, which might contain > some implementation-dependent things it needs. Everything Foo references must *also* be moved to the spec for this idea to work. That's annoying, but it is not in principle different from the fact that everything a private type refers to must be in the spec: type T is private; ... Max: constant := 1234; type My_Int is range 1..Max; function F return My_Int; type T is record X: My_Int := F(...); Because Ada requires the full type of T to occur in the spec, it also implicitly requires Max, My_Int, and F to be declared in the spec. > > 2. Put the private info in the body. But let the compiler "peek" into > > the body in some cases (pragma Inline present, inlining-enabled > > switch turned on, phase of moon is blue, etc). This is what Ada does > > for the inlined-call case. I would claim Ada *could* do something > > similar for the private type case. (Note that in languages where > > "everything's a pointer", you get this kind of (lack of) efficiency.) > > > > This idea seems nice in that it gives the programmer control over the > > compile-time speed vs. run-time speed trade-off. (By the way, I > > claim that computers are many years away from being so fast that this > > tradeoff doesn't matter. Especially since every hardware gain is > > offset by more software bloat.) > > Sort of pragma Inline for incomplete types and values (deferred constants)? Yeah. > Do you think it is technically possible? Yes. It would cause some pretty slow code without the Inline_Type, but that's the programmer's choice (compile-time efficiency vs run-time efficiency). >... I has not much thought about it, > but we must ensure absence of any circular dependencies, which could > prevent compiler from calculation of the object size. Yes. Ada already has a rule that type T cannot have a [sub]component of type T (the programmer has to insert a level of indirection). This rule would have to be removed, because the compiler doesn't always see the full type. This would mean that the *compiler* would be responsible for inserting the extra level of indirection. (This is similar to what happens in Java and other "everything's a pointer" sorts of languages -- in those languages, there is *always* an extra level of indirection.) Another problem is parameter passing mechanisms. Ada defines it to be by-copy for some types, by-reference for some types, and compiler-choice for some types. It would be pretty disgusting (from an efficiency point of view) if this choice had to be made at run time. But this is an Ada-specific issue. I don't like the Ada rules here, and we're talking about languae design (an Ada-like language that is not Ada), so it's fair for me to ignore this issue. > > 3. Define packages as *three* parts: the interface, the > > efficiency-critical parts of the implementation, and the > > implementation. > > The second part is really the "private part" of Ada, but split > > out into a separate syntactic unit (probably in a separate file). > > In the traditional Ada compiler dependency setup, a change to the > > second part would trigger recompilation of all with-ing compilation > > units. > > This is attractive, because with tagged types [especially when you need to > add some public and some private components] the specifications get too > long. It is also good because then one could require that the compiler > never ever looks in *.adb. But does not it also suffer the problem of > not-seeing *.adb? No big problem -- as I said above, it just means that everything referenced in the second part (transitively) has to be declared in the second part. Not necessarily their "bodies" (or "full types"), unless you want *those* inlined, too. No such thing as a free lunch. ;-) > > I claim that any of these 3 possibilities is suitable for the > > private-type case, and the inline-procedure case, and every other case. > > I also claim that it would simplify the language to choose one of the > > above, and use it for all such interface-vs-impl kinds of features. > > > > I lean toward 2, but 3 also has merit. Number 1, as in Ada private > > types, has a severe disadvantage: you can't put the full type in a > > different file from the private type. It doesn't get a different > > revision number in the CM system. And if you have multiple versions > > (say, for different target hardware), you have to duplicate the visible > > part. > > What if to allow something like: > > package X > ... > private is separate; > end X; > > Then there should be X-XX.ads containing a completion of X. Right. I think I remember the GNAT folks talking about implementing something like this. The idea was that the RM doesn't define the "source representation" of compilation_units, so there's nothing wrong with an implementation allowing (or requiring?!) the private part to be in a different file. Good idea, but if the language were designed with that in mind, it would work more smoothly in practise. The language heavily *implies* that each compilation_unit be represented as a contiguous piece of text in one file. For example, the private part syntax doesn't include the package name at the front. Also, there's the issue of with_clauses. It would be nice to attach with_clauses to the private_part. - Bob