// file : frontend-elements/traversal.hxx // author : Boris Kolpackov // copyright : Copyright (c) 2005-2010 Boris Kolpackov // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #ifndef FRONTEND_ELEMENTS_TRAVERSAL_HXX #define FRONTEND_ELEMENTS_TRAVERSAL_HXX #include #include #include #include #include #include //@@ Move to trace next time you are about to uncomment this. // // #include // using std::wcerr; // using std::endl; namespace FrontendElements { namespace Traversal { // // template class TraverserBase { protected: virtual ~TraverserBase (); virtual Void trampoline (X&) = 0; virtual Void trampoline (X const&) = 0; template friend class DispatcherBase; }; // // template class DispatcherBase { typedef Cult::RTTI::TypeId TypeId; typedef Cult::RTTI::TypeInfo TypeInfo; public: virtual ~DispatcherBase (); virtual Void dispatch (X&); virtual Void dispatch (X const&); Void map (TypeId id, TraverserBase& t) { //wcerr << "map for " << id.name () << " to " << &t // << " in " << &traversal_map_ << endl; Traversers& traversers (traversal_map_[id]); traversers.push_back (&t); } public: typedef Cult::Containers::Vector*> Traversers; typedef Cult::Containers::Map TraversalMap; typedef typename TraversalMap::ConstIterator Iterator; Iterator begin () const { return traversal_map_.begin (); } Iterator end () const { return traversal_map_.end (); } protected: static Cult::Trace::Stream tout; private: template Void dispatch_ (Y&); private: struct TypeInfoComparator { Boolean operator () (TypeInfo const& a, TypeInfo const& b) const { return a.type_id () < b.type_id (); } }; typedef Cult::Containers::Map LevelMap; typedef Cult::Containers::Set TypeInfoSet; static UnsignedLong compute_levels (TypeInfo const& ti, UnsignedLong cur, LevelMap& map); static Void flatten_tree (TypeInfo const& ti, TypeInfoSet& set); private: TraversalMap traversal_map_; }; // // template class Dispatcher: public virtual DispatcherBase { public: Dispatcher () : merge_ (true) { } Void traverser (DispatcherBase& d) { for (typename DispatcherBase::Iterator i (d.begin ()), e (d.end ()); i != e; ++i) { for (typename DispatcherBase::Traversers::ConstIterator t (i->second.begin ()), e (i->second.end ()); t != e; ++t) { dispatcher_.map (i->first, **t); } } } public: virtual Void dispatch (X& x) { merge (); dispatcher_.dispatch (x); } virtual Void dispatch (X const& x) { merge (); dispatcher_.dispatch (x); } using DispatcherBase::begin; using DispatcherBase::end; private: Void merge () { if (merge_) { for (typename DispatcherBase::Iterator i (begin ()), e (end ()); i != e; ++i) { for (typename DispatcherBase::Traversers::ConstIterator t (i->second.begin ()), e (i->second.end ()); t != e; ++t) { dispatcher_.map (i->first, **t); } } merge_ = false; } } protected: template Void iterate_and_dispatch (I begin, I end, DispatcherBase& d) { for (; begin != end; ++begin) { d.dispatch (*begin); } } template Void iterate_and_dispatch (I begin, I end, DispatcherBase& d, T& t, Void (T::*next)(A&), A& a) { for (; begin != end;) { d.dispatch (*begin); if (++begin != end && next != 0) (t.*next) (a); } } private: Boolean merge_; DispatcherBase dispatcher_; }; // // template struct Traverser : TraverserBase, virtual Dispatcher { typedef T Type; Traverser () { map (typeid (Type), *this); } virtual Void traverse (Type&) { abort (); } virtual Void traverse (Type const&) { abort (); } protected: virtual Void trampoline (X& x) { //wcerr << "trampoline for " << &i << " to type " // << typeid (type).name () << endl; traverse (dynamic_cast (x)); } virtual Void trampoline (X const& x) { //wcerr << "trampoline for " << &i << " to type " // << typeid (Type).name () << endl; traverse (dynamic_cast (x)); } }; } } #include #include #endif // FRONTEND_ELEMENTS_TRAVERSAL_HXX