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.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,4ed596f1f077b44e X-Google-Attributes: gid103376,public From: bobduff@world.std.com (Robert A Duff) Subject: Re: Primitive Operations Question Date: 1996/08/01 Message-ID: #1/1 X-Deja-AN: 171426961 references: <31FE812C.7B3D@ix.netcom.com> organization: The World Public Access UNIX, Brookline, MA newsgroups: comp.lang.ada Date: 1996-08-01T00:00:00+00:00 List-Id: In article , Jon S Anthony wrote: >... Or is there something more mysterious going on here? No. >BTW, I have wondered at times why there was this restriction as >opposed to allowing any operation within the same immediate scope of >the type declaration be primitive. ... If I remember correctly, the rules were slightly different in an earlier version of Ada 9X, something along the lines of what you say. I don't remember all the reasons why we changed it, but here are some issues: If you have a type declared in a package spec, you don't want to allow adding new primitives in the body, even though spec and body together form a single declarative region. (The rules never allowed this, by the way.) This is so that the compiler can lay out the type descriptor at compile time, and is explained in the AARM. Allowing primitive ops in declarative parts isn't particularly useful, so it shouldn't be allowed unless it's truly harmless. Tagged types are a powerful abstraction mechanism, so one would normally want to put them in a library package spec anyway. Also, the freezing rules don't allow you to declare primitives using spec-less subprograms, so you need explicit specs anyway, so it's not too onerous to require wrapping it all in a package. Also, the accessibility rules say that if a given tagged type is in a procedure body, then the entire hierarchy must be in that same procedure body, to prevent dangling references. That is, we never seriously considered allowing type extensions inside a procedure, when the parent type is outside (although one distinguished reviewer did push for that). Although you can't declare new primitive ops except in a package spec, you can override in a package body. This allows, for example: type Whatever is new Limited_Controlled with null record; procedure Finalize(X: in out Whatever); X: Whatever; in a library package body (without a wrapper spec). Finalize will get called just before program exit. Wrapping the type and its primitives makes things look more encapsulated, and makes it easier to find the primitives. Note that some folks who are used to the Eiffel or C++ way of doing things have criticized Ada because they see even the current rule as not enough (they want all the primitive ops to be *inside* the type/class). I don't really agree with that criticism, but making the rule even looser would make that criticism a bit closer to the truth. Ada 83 already had a notion of "derivable subprograms", which we now call "primitive subprograms". We wanted to keep that rule the same as in Ada 83 for untagged types, for upward compatibility. We wanted to make the rules for tagged types as friendly as possible. And we wanted to make the rules for tagged and untagged types the same, for uniformity. These are conflicting goals, and we did end up changing the rules for Ada 83 untagged types, but not as much as your suggestion would imply (unless you suggest sacrificing uniformity between tagged and untagged). That's all I can think of right now. Tucker can probably think of some killer semantic anomoly that forced the issue. - Bob