comp.lang.ada
 help / color / mirror / Atom feed
From: Adam Beneschan <adam@irvine.com>
Subject: Re: Primitive curiosity...
Date: Wed, 17 Sep 2008 14:19:47 -0700 (PDT)
Date: 2008-09-17T14:19:47-07:00	[thread overview]
Message-ID: <f3c7099d-7406-4c6e-9a49-c0eba5205a95@q5g2000prf.googlegroups.com> (raw)
In-Reply-To: 447b8b2a-b7bb-4ff5-89bf-a6b7eecc054e@a70g2000hsh.googlegroups.com

On Sep 17, 1:29 pm, mockturtle <framefri...@gmail.com> 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




  parent reply	other threads:[~2008-09-17 21:19 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-17 20:29 Primitive curiosity mockturtle
2008-09-17 21:13 ` Jeffrey R. Carter
2008-09-17 21:19 ` Adam Beneschan [this message]
2008-09-18 19:27   ` mockturtle
2008-09-24 14:02   ` Martin
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox