// file : frontend-elements/traversal.txx // author : Boris Kolpackov // copyright : Copyright (c) 2005-2010 Boris Kolpackov // license : GNU GPL v2 + exceptions; see accompanying LICENSE file namespace FrontendElements { namespace Traversal { // TraverserBase // template TraverserBase:: ~TraverserBase () { } // DispatcherBase // template DispatcherBase:: ~DispatcherBase () { } template Void DispatcherBase:: dispatch (X& x) { dispatch_ (x); } template void DispatcherBase:: dispatch (X const& x) { dispatch_ (x); } template template void DispatcherBase:: dispatch_ (Y& y) { LevelMap levels; TypeInfo const& ti (Cult::RTTI::lookup (typeid (y))); UnsignedLong max (compute_levels (ti, 0, levels)); tout << "starting dispatch process for " << ti.type_id ().name () << " with " << max << " levels"; for (UnsignedLong l (0); l < max + 1; ++l) { TypeInfoSet dispatched; for (typename LevelMap::ConstIterator i (levels.begin ()), e (levels.end ()); i != e; ++i) { if (i->second == l) { typename TraversalMap::ConstIterator v ( traversal_map_.find (i->first.type_id ())); if (v != traversal_map_.end ()) { tout << "dispatching traversers for " << ti.type_id ().name () << " as " << i->first.type_id ().name (); Traversers const& traversers (v->second); for (typename Traversers::ConstIterator ti (traversers.begin ()), te (traversers.end ()); ti != te; ++ti) { (*ti)->trampoline (y); } flatten_tree (i->first, dispatched); } } } // Remove traversed types from the level map. // for (typename TypeInfoSet::ConstIterator i (dispatched.begin ()); i != dispatched.end (); ++i) { levels.erase (*i); } } } template UnsignedLong DispatcherBase:: compute_levels (TypeInfo const& ti, UnsignedLong cur, LevelMap& map) { UnsignedLong ret (cur); if (map.find (ti) == map.end () || map[ti] < cur) map[ti] = cur; for (TypeInfo::BaseIterator i (ti.begin_base ()); i != ti.end_base (); ++i) { UnsignedLong tmp (compute_levels (i->type_info (), cur + 1, map)); if (tmp > ret) ret = tmp; } return ret; } template Void DispatcherBase:: flatten_tree (TypeInfo const& ti, TypeInfoSet& set) { set.insert (ti); for (TypeInfo::BaseIterator i = ti.begin_base (); i != ti.end_base (); ++i) { flatten_tree (i->type_info (), set); } } template Cult::Trace::Stream DispatcherBase:: tout ("frontend-elements::traversal", 5); } }