summaryrefslogtreecommitdiff
path: root/contrib/utility/Example/Introspection/Traversal/Traversal.cpp
blob: 9fa94327c2ce2e3730fc76ea9e972b5ab86793ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// file      : Example/Introspection/Traversal/Traversal.cpp
// author    : Boris Kolpackov <boris@kolpackov.net>
// copyright : Copyright (c) 2002-2003 Boris Kolpackov
// license   : http://kolpackov.net/license.html

#include "Traversal.hpp"

#include <set>
#include <map>

using namespace Utility::Introspection;

namespace Traversal
{
  // Dispatcher
  //
  //

  struct TypeInfoComparator
  {
    bool
    operator () (TypeInfo const& x, TypeInfo const& y) const
    {
      return x.type_id () < y.type_id ();
    }
  };

  typedef
  std::map<TypeInfo, unsigned long, TypeInfoComparator>
  LevelMap;

  typedef
  std::set<TypeInfo, TypeInfoComparator>
  TypeInfoSet;

  unsigned long
  compute_levels (TypeInfo const& ti, unsigned long cur, LevelMap& map)
  {
    unsigned long 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++)
    {
      unsigned long t = compute_levels (i->type_info (), cur + 1, map);
      if (t > ret) ret = t;
    }

    return ret;
  }

  void
  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);
    }
  }

  void Dispatcher::
  dispatch (SyntaxTree::Node* n)
  {
    LevelMap levels;

    unsigned long max = compute_levels (n->type_info (), 0, levels);

    for (unsigned long l = 0; l < max + 1; l++)
    {
      TypeInfoSet dispatched;

      for (LevelMap::const_iterator i = levels.begin ();
           i != levels.end ();
           i++)
      {
        if (i->second == l)
        {
          TraversalMap::const_iterator v =
            traversal_map_.find (i->first.type_id ());

          if (v != traversal_map_.end ())
          {
            v->second->traverse (n);
            flatten_tree (i->first, dispatched);
          }
        }
      }

      // Remove traversed types from level map.
      for (TypeInfoSet::const_iterator i = dispatched.begin ();
           i != dispatched.end ();
           i++)
      {
        levels.erase (*i);
      }
    }
  }
}
//$Id$