From: Stefan S. <se...@sy...> - 2004-06-08 13:20:05
|
Grzegorz Jakacki wrote: >>>I did not mean what you understood. In fact I want Node<Definition> to be >>>"abstract". The second part of example was a miss, let me fix it: >>> >>> Node<Definition> d = ParseDefinition("int main() {}"); >>> SomeVisitor v; >>> v(d); //<--- calls v.Visit(Node<FunctionDefinition>) >> >>Ah, so 'ParseDefinition()' is an 'abstract factory' ? > > > Exactly. > > (Observe, that rParseDefition() in current code is an Abstract > Factory for Ptree hierarchy.) Indeed. But Then you can't simply assign to a Node<Definition> without a downcast. That was what I stumbled over :-) >>That means >>that all those 'Node<>' classes derive from an abstract 'NodeBase' class, > > > Nope. Read "Node<>", think "smart pointer". ok. But that's a different issue. Whether we use smart pointers or not, somewhere we need a class hierarchy with a type system that covers *all* the C++ grammar. > > Node<> is intended to be a smart pointer with shallow copy. > > Node<FunctionDefinition> will have default conversion to Node<Definition>. > > Visitor for Node<> hierarchy will dispatch Node<Definition> to > Visit(Node<FunctionDefition>), Visit(Node<ClassDefinition>) etc. that's possible but sounds a bit complicated, since even though 'FunctionDefinition' IsA 'Definition', but 'Node<FunctionDefinition>' is *not* a 'Node<Definition>'. I.e. in the former case the compiler and the C++ type system would do the proper dispatching for us, but when using the indirection over Node<> smart pointers we'd have to do that manually. That's why I'd like to keep the discussion to the AST type hierarchy separate from the issue of whether or not to use Node<> smart pointers. >>at which point I'm wondering what the advantage of such a templated >>class hierarchy is as opposed to a simple traditional one >>(i.e. instead of 'Node<Foo>' just using 'Foo', as 'Foo' would need to >>be defined anyways) > > > Foo does not need to be defined, declaration alone is sufficient. But we > can also reuse PtreeXxxx classes for Foo (that would make sense that in > general Node<PtreeIfStatement> is a wrapper for PtreeIfStatement*). When is a declaration sufficient ? > The advantage of using Node<Foo> over using Foo* is that > Node<> wrappers do not expose Car/Cdr. yeah, I see your point. Well, what about deriving privately from Ptree and then raising the const methods into the public API via 'using' directives ? That has the additional benefit of preserving the type system for us to play with. > Moreover, in some cases determining the nature of a Ptree (e.g. if it is > if-then, or if-then-else) requires some code (e.g. go to > Car()->Car()->Car()->Cdr() and check if it is NULL). Ptree hierarchy has > only PtreeIfStatement, which covers both if-then and if-then-else. Having > Node<> wrapper we can have Node<IfThen> and Node<IfThenElse>, both > wrapping PtreeIfStatement*, but carrying additionial information in the > wrapper type. hmm, the 'ctool' backend I was talking about earlier has an 'IfStatement' that looks about so: struct IfStatement : Statement { Expression *condition; Statement *then_block; Statement *else_block; }; where the 'else_block' can be empty. I like the simplicity of this, even though I'd encapsulate it a little more (especially if this is just a ptree wrapper). > Yet another argument is that this kind of API is trurly and *interface* to > the tree data. Node<> scheme allows to have many interfaces. In particular, > recall my example of how people want "+" node to be exposed in API --- some > want to see "+" as a binary operator, others as a multiary one. Assuming > that Node<> shows binary plus, client can write/generate another API, that > will expose "multiary" plus. Clients using different APIs can still exchange > the underlying Ptree datastructure, they just see different views. yeah, I agree in general that delegation is often better than derivation. My real issue here is, as I said, the lost of the type system. Could you demonstrate how a Node<> based visitor would be implemented (i.e. how it would resolve the correct type) ? As that's the central point I believe, I'll wait before I continue arguing about the other points until my understanding of this Node<> visitor as you see it is more complete. Regards, Stefan |