Re: C++ nested classes, namespaces, structs, and compound statements

Daniel Jacobowitz
2002-04-10T03:56:06Z

I'm going to answer out-of-order a little bit, so pardon the
cut-n-paste butchery.

> I feel like we're planning a construction project like Boston's Big
> Dig or something: everything's got to keep running while we do the
> work, and things will get pretty ugly in there for a while, but we
> hope (if our funding doesn't run out) that in the end it'll all be
> beautiful.
>

As much of a pain as they are, I recommend a CVS branch for this. Then
we can see how it comes together with some history and a little less
destabilization. We still need to know where we're going first, of
course.

On Tue, Apr 09, 2002 at 08:35:52PM -0500, Jim Blandy wrote:
>
> Ah, this is exactly the kind of debate I was looking for. :)
>
> Daniel Jacobowitz <drow@mvista.com> writes:
> > But let me put my cynic's cap on for a moment and point out some
> > problems. I'd love to see us just decide to overcome them all, and I
> > think it's viable, but we need to make sure we consider them first.
> >
> > The "incremental change" Problem
>
> This I especially suck at. So folks, please insist on getting an
> answer you're really comfortable with.
>
> Here's one way we could approach it:
>
> - First, we could simply replace the `nsyms' and `syms' members of
> `struct block' with a reference to our opaque `environment' object.
> There isn't that much code which works on those directly, so this
> wouldn't be too bad.

And most of it will be very easy to find, because I went through all of
it quite recently. Remember my tries last October or so to change syms
from a list to a hash table? I've still got all that code, and while
none of it went in, at least I cleaned up every access to those members
I can find. Everything that iterates over them (with perhaps one
exception in the COFF code, IIRC) uses ALL_BLOCK_SYMBOLS. All accesses
go through the proper macros.

> - Next, we could replace the static and global blocks with `environment'
> objects, too.
>
> At this point, our environment object would be known to work. *ahem*
>
> - Make accessing a symbol's name go through an accessor function. It
> goes through a macro already, but we'd have to make sure it *always*
> goes through the macro. (Renaming the structure member and tweaking
> the macro accordingly would help us find code which doesn't go
> through the macro.)
>
> - Then we could go through an intermediate phase where things worked
> like this:
>
> a) The symbol table stores names either way: with an explicit
> namespace tree, or with qualified names sitting directly in the
> symbol table. (When I say "namespace", please understand that to
> also include classes, etc.) Any given symbol is stored only one
> way or the other, but any given symbol table can hold a mix of
> symbols in each form. Symbols stored in the explicit tree would
> have a `fully_qualified_name' field, so symtab clients expecting
> to see fully qualified names would still get them.

OK so far... we might want to take the path of least resistence, leave
the name fully qualified, and add an unqualified_name.

> b) The object representing a namespace keeps around the prefix it
> corresponds to (`std::' or `A::B::' or whatever), so that lookups of
> single name components relative to that namespace can find entries
> stored in either form.
>
> c) For backwards compatibility, the symbol lookup function would check
> for `::' in symbol names, and do a component-by-component lookup.

We might also want to check for '.', as per Java (in existing gcj
versions, at least).

> Then, we could gradually do the following (some of these are
> interdependent, some not):
>
> - Change symbol table clients to call a function to print a symbol's
> qualified name relative to the current scope, rather than expecting
> to see a fully qualified name in the symbol structure itself. This
> would make b) unnecessary.
>
> - Change symbol table clients to do lookups one component at a time,
> making c) unnecessary.
>
> - Change symbol table readers to build explicit namespace trees,
> rather than dumping qualified names into the symbol table. This
> would make a) unnecessary.
>
> Now we've got symbol lookups switched over. Given the new
> representation, we can implement namespaces in a straightforward way.
>
> But what about structs? I don't have enough of a grasp on how data
> members, member functions, static members, etc. really work now to say
> how we'd switch struct types over to the new representation, but it
> seems like the same general approach should work:
>
> - Gradually replace code which manipulates the type structures
> directly with simple accessor functions, until the type can be made
> opaque.

They mostly are, already.

> - Switch to an intermediate representation which allows both the old
> and the new representations, mixed.

Not for a given type, certainly. So not quite the same as with
symbols; a type would be one or the other.

> - Migrate clients and producers over to the newer interfaces. This is
> now a set of independent changes, that can be done in any order.
>
> - Once the producers are all creating data in the new style, remove
> support for it. Now you've got your new data structure, used as an
> opaque datatype.

And hopefully we'd reach this step, rather than being left with the
mess in the middle.

I like it. Who wants to start? :) We probably want to start with
interfaces, and then see where we need to go from there.

--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer