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-Thread: 103376,9cff4fb5d12e1f68 X-Google-Attributes: gid103376,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!postnews.google.com!q5g2000prf.googlegroups.com!not-for-mail From: Adam Beneschan Newsgroups: comp.lang.ada Subject: Re: Primitive curiosity... Date: Wed, 17 Sep 2008 14:19:47 -0700 (PDT) Organization: http://groups.google.com Message-ID: References: <447b8b2a-b7bb-4ff5-89bf-a6b7eecc054e@a70g2000hsh.googlegroups.com> NNTP-Posting-Host: 66.126.103.122 Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Trace: posting.google.com 1221686387 25512 127.0.0.1 (17 Sep 2008 21:19:47 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Wed, 17 Sep 2008 21:19:47 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: q5g2000prf.googlegroups.com; posting-host=66.126.103.122; posting-account=duW0ogkAAABjRdnxgLGXDfna0Gc6XqmQ User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.12) Gecko/20050922 Fedora/1.7.12-1.3.1,gzip(gfe),gzip(gfe) Xref: g2news1.google.com comp.lang.ada:2034 Date: 2008-09-17T14:19:47-07:00 List-Id: On Sep 17, 1:29 pm, mockturtle wrote: > Dear *, > I was doing some experiments with dispatching operations > and I discovered something that made me curious... Consider > the following 3-file set: 1 package (base.ad?) with a > "root" abstract type (Root) and two derived types > (Derived_1 and Derived_2) and 1 "main" (test_bas.adb) [source code snipped] > The idea is that the first line in Test_Base should call > Print of Derived_1 and the second line should call > procedure Print of Derived_2. In order to compile, one must > uncomment LINE A or LINE B (but not both) in > base.ads. > > Now the fun bit comes > > 1) If I uncomment LINE A everything is fine, but... > 2) if I uncomment LINE B gcc (4.1.3) complaints with > .... other lines .... > base.ads:19:14: this primitive operation is declared too late > > I interpreted the "immediately within" in the sentence > [AARM05 3.2.3(2/6)] > > "The primitive subprograms of a specific type are > defined as follows: > [...] > * For a specific type declared immediately within > a package_specification, any subprograms > (in addition to the enumeration literals) that are > explicitly declared _immediately_within_ the same > package_specification and that operate on the type;" > > as "declared in the same file as the type", but according > to the behaviour described above (and some other > experiments) it seems that there is > a further constraint "before the declaration of any > derived type." I realize this post wasn't addressed to me, since my name is /, not *. Or maybe it's %. Anyway, though, the error message is correct. See 13.14(16) and 13.14(7). What's going on here is this: A type is "frozen" when it is used in certain contexts; the idea is that the representation of the type must have been completely determined by the time it's used in one of these contexts, and you can't write (say) a representation clause for one of those types after the compiler has already used the information. For example, if you declare a variable V of a type T, the compiler will allocate space for the variable V; if you then do something after the variable declaration that could change the size of T, the compiler will tear its hair out and complain "Why didn't you tell me that earlier???!!!" Or, at least that's approximately how I'd react if my wife did that to me. But anyway, that's the whole point of the freezing rules. For a tagged type, the things that need to be determined before it's frozen include something sometimes called the "dispatch vector" or "dispatch table" or something like that. It's basically a table that contains the addresses of the primitive subprograms of the type. Type extensions that may override those subprograms will have their own array with the primitive subprograms in the same slots in the array. Then, when you do a dispatching operation, the code generated by the compiler will just look in that slot in the array to see what procedure to execute. That's how polymorphism takes place. But this requires that the dispatch table be completed before it's used. When you declare a type extension, it will inherit the root type's primitive operations, but you can declare *new* operations of the type extension (and its descendants), which will need to be put into new slots in the array. For this to happen, the compiler has to know already how many slots will be allocated to the primitive subprograms of the parent type. The number of subprograms of the parent type is then frozen, so that the compiler can safely allocate slots beyond that for operations of the child types. Therefore, if the language let you declare a new primitive subprogram of the parent type after the compiler already needed to know how many primitive subprograms there were going to be, it would screw everything up, because the compiler already thought it knew how many primitive operations of the parent type there were going to be, and here you are adding a new one, and the compiler can't do anything except tell you "You shoulda told me about that earlier". Which, in effect, what the error message is doing. Hope this helps explain things, -- Adam